Compare commits
3 Commits
4b281aae77
...
2554b80359
| Author | SHA1 | Date | |
|---|---|---|---|
| 2554b80359 | |||
| 54d9ef56a2 | |||
| 7a2a72a554 |
|
|
@ -475,16 +475,16 @@ class StackedRouter extends _i1.RouterBase {
|
|||
_i18.LearnModuleView: (data) {
|
||||
final args = data.getArgs<LearnModuleViewArguments>(nullOk: false);
|
||||
return _i37.MaterialPageRoute<dynamic>(
|
||||
builder: (context) =>
|
||||
_i18.LearnModuleView(key: args.key, course: args.course),
|
||||
builder: (context) => _i18.LearnModuleView(
|
||||
key: args.key, first: args.first, course: args.course),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
_i19.LearnLessonView: (data) {
|
||||
final args = data.getArgs<LearnLessonViewArguments>(nullOk: false);
|
||||
return _i37.MaterialPageRoute<dynamic>(
|
||||
builder: (context) =>
|
||||
_i19.LearnLessonView(key: args.key, module: args.module),
|
||||
builder: (context) => _i19.LearnLessonView(
|
||||
key: args.key, first: args.first, module: args.module),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
|
|
@ -628,7 +628,8 @@ class StackedRouter extends _i1.RouterBase {
|
|||
_i35.LearnCourseView: (data) {
|
||||
final args = data.getArgs<LearnCourseViewArguments>(nullOk: false);
|
||||
return _i37.MaterialPageRoute<dynamic>(
|
||||
builder: (context) => _i35.LearnCourseView(key: args.key, id: args.id),
|
||||
builder: (context) =>
|
||||
_i35.LearnCourseView(key: args.key, id: args.id, first: args.first),
|
||||
settings: data,
|
||||
);
|
||||
},
|
||||
|
|
@ -1009,54 +1010,60 @@ class LoginViewArguments {
|
|||
class LearnModuleViewArguments {
|
||||
const LearnModuleViewArguments({
|
||||
this.key,
|
||||
required this.first,
|
||||
required this.course,
|
||||
});
|
||||
|
||||
final _i37.Key? key;
|
||||
|
||||
final bool first;
|
||||
|
||||
final _i38.LearnCourse course;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{"key": "$key", "course": "$course"}';
|
||||
return '{"key": "$key", "first": "$first", "course": "$course"}';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant LearnModuleViewArguments other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other.key == key && other.course == course;
|
||||
return other.key == key && other.first == first && other.course == course;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return key.hashCode ^ course.hashCode;
|
||||
return key.hashCode ^ first.hashCode ^ course.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
class LearnLessonViewArguments {
|
||||
const LearnLessonViewArguments({
|
||||
this.key,
|
||||
required this.first,
|
||||
required this.module,
|
||||
});
|
||||
|
||||
final _i37.Key? key;
|
||||
|
||||
final bool first;
|
||||
|
||||
final _i39.LearnModule module;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{"key": "$key", "module": "$module"}';
|
||||
return '{"key": "$key", "first": "$first", "module": "$module"}';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant LearnLessonViewArguments other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other.key == key && other.module == module;
|
||||
return other.key == key && other.first == first && other.module == module;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return key.hashCode ^ module.hashCode;
|
||||
return key.hashCode ^ first.hashCode ^ module.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1486,26 +1493,29 @@ class LearnCourseViewArguments {
|
|||
const LearnCourseViewArguments({
|
||||
this.key,
|
||||
required this.id,
|
||||
required this.first,
|
||||
});
|
||||
|
||||
final _i37.Key? key;
|
||||
|
||||
final int id;
|
||||
|
||||
final bool first;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '{"key": "$key", "id": "$id"}';
|
||||
return '{"key": "$key", "id": "$id", "first": "$first"}';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant LearnCourseViewArguments other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other.key == key && other.id == id;
|
||||
return other.key == key && other.id == id && other.first == first;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return key.hashCode ^ id.hashCode;
|
||||
return key.hashCode ^ id.hashCode ^ first.hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1801,6 +1811,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
|
||||
Future<dynamic> navigateToLearnModuleView({
|
||||
_i37.Key? key,
|
||||
required bool first,
|
||||
required _i38.LearnCourse course,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -1809,7 +1820,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return navigateTo<dynamic>(Routes.learnModuleView,
|
||||
arguments: LearnModuleViewArguments(key: key, course: course),
|
||||
arguments:
|
||||
LearnModuleViewArguments(key: key, first: first, course: course),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
@ -1818,6 +1830,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
|
||||
Future<dynamic> navigateToLearnLessonView({
|
||||
_i37.Key? key,
|
||||
required bool first,
|
||||
required _i39.LearnModule module,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -1826,7 +1839,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return navigateTo<dynamic>(Routes.learnLessonView,
|
||||
arguments: LearnLessonViewArguments(key: key, module: module),
|
||||
arguments:
|
||||
LearnLessonViewArguments(key: key, first: first, module: module),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
@ -2107,6 +2121,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
Future<dynamic> navigateToLearnCourseView({
|
||||
_i37.Key? key,
|
||||
required int id,
|
||||
required bool first,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
Map<String, String>? parameters,
|
||||
|
|
@ -2114,7 +2129,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return navigateTo<dynamic>(Routes.learnCourseView,
|
||||
arguments: LearnCourseViewArguments(key: key, id: id),
|
||||
arguments: LearnCourseViewArguments(key: key, id: id, first: first),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
@ -2399,6 +2414,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
|
||||
Future<dynamic> replaceWithLearnModuleView({
|
||||
_i37.Key? key,
|
||||
required bool first,
|
||||
required _i38.LearnCourse course,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -2407,7 +2423,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return replaceWith<dynamic>(Routes.learnModuleView,
|
||||
arguments: LearnModuleViewArguments(key: key, course: course),
|
||||
arguments:
|
||||
LearnModuleViewArguments(key: key, first: first, course: course),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
@ -2416,6 +2433,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
|
||||
Future<dynamic> replaceWithLearnLessonView({
|
||||
_i37.Key? key,
|
||||
required bool first,
|
||||
required _i39.LearnModule module,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
|
|
@ -2424,7 +2442,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return replaceWith<dynamic>(Routes.learnLessonView,
|
||||
arguments: LearnLessonViewArguments(key: key, module: module),
|
||||
arguments:
|
||||
LearnLessonViewArguments(key: key, first: first, module: module),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
@ -2705,6 +2724,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
Future<dynamic> replaceWithLearnCourseView({
|
||||
_i37.Key? key,
|
||||
required int id,
|
||||
required bool first,
|
||||
int? routerId,
|
||||
bool preventDuplicates = true,
|
||||
Map<String, String>? parameters,
|
||||
|
|
@ -2712,7 +2732,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
|
|||
transition,
|
||||
}) async {
|
||||
return replaceWith<dynamic>(Routes.learnCourseView,
|
||||
arguments: LearnCourseViewArguments(key: key, id: id),
|
||||
arguments: LearnCourseViewArguments(key: key, id: id, first: first),
|
||||
id: routerId,
|
||||
preventDuplicates: preventDuplicates,
|
||||
parameters: parameters,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class AuthenticationService with ListenableServiceMixin {
|
|||
|
||||
// Initialization
|
||||
AuthenticationService() {
|
||||
listenToReactiveValues([_user,_state, _localizationService]);
|
||||
listenToReactiveValues([_user, _state, _localizationService]);
|
||||
}
|
||||
|
||||
// Logout state
|
||||
|
|
@ -31,7 +31,6 @@ class AuthenticationService with ListenableServiceMixin {
|
|||
|
||||
StateObjects get state => _state;
|
||||
|
||||
|
||||
// Check user logged in
|
||||
Future<bool> userLoggedIn() async {
|
||||
if (await _secureService.getString('userId') != null) {
|
||||
|
|
@ -202,7 +201,6 @@ class AuthenticationService with ListenableServiceMixin {
|
|||
await setFirstTimeInstall(firstTimeInstall);
|
||||
await _secureService.setString('language', language);
|
||||
|
||||
|
||||
_state = StateObjects.none;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ class GoogleAuthService with ListenableServiceMixin {
|
|||
|
||||
_googleUser ??=
|
||||
await _signIn.authenticate(scopeHint: ['email', 'profile']);
|
||||
|
||||
});
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -58,8 +58,6 @@ class LearnService with ListenableServiceMixin {
|
|||
|
||||
List<LearnLesson> get lessons => _lessons;
|
||||
|
||||
|
||||
|
||||
// Learn programs
|
||||
Future<String?> refreshObject(String url) async {
|
||||
Map<String, dynamic> data = {'reference': url};
|
||||
|
|
|
|||
|
|
@ -124,5 +124,4 @@ String kTelegramSupportLink = 'https://t.me/yimaruacademy2026';
|
|||
|
||||
String kErrorUrl = 'https://api.yimaruacademy.com/payment/error';
|
||||
|
||||
String kSuccessUrl =
|
||||
'https://api.yimaruacademy.com/payment/success';
|
||||
String kSuccessUrl = 'https://api.yimaruacademy.com/payment/success';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import 'dart:ui';
|
|||
|
||||
import 'package:easy_localization/easy_localization.dart' show AssetLoader;
|
||||
|
||||
class CodegenLoader extends AssetLoader{
|
||||
class CodegenLoader extends AssetLoader {
|
||||
const CodegenLoader();
|
||||
|
||||
@override
|
||||
|
|
@ -14,7 +14,7 @@ class CodegenLoader extends AssetLoader{
|
|||
return Future.value(mapLocales[locale.toString()]);
|
||||
}
|
||||
|
||||
static const Map<String,dynamic> _am = {
|
||||
static const Map<String, dynamic> _am = {
|
||||
"loading": "በመጫን ላይ",
|
||||
"welcome_back": "እንኳን በደህና ተመለሱ",
|
||||
"checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ",
|
||||
|
|
@ -38,7 +38,8 @@ class CodegenLoader extends AssetLoader{
|
|||
"confirm_password": "የይለፍ ቃል ያረጋግጡ",
|
||||
"eight_character_minimum": "ቢያንስ 8 ፊደላት",
|
||||
"password_match": "የይለፍ ቃሉ ተመሳስሏል",
|
||||
"sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።",
|
||||
"sign_up_agreement":
|
||||
"‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።",
|
||||
"terms_of_services": "የአገልግሎት ውሎች",
|
||||
"and": "እና",
|
||||
"privacy_policy": "የግላዊነት ፖሊሲ",
|
||||
|
|
@ -137,7 +138,8 @@ class CodegenLoader extends AssetLoader{
|
|||
"call_our_support": "ከ3 ጠዋት እስከ 12 ማታ ድረስ የድጋፍ ቡድናችንን ይደውሉ",
|
||||
"tap_to_call": "ለመደወል ይንኩ",
|
||||
"join_telegram": "በቴሌግራም የይማሩ አካዳሚን ይቀላቀሉ",
|
||||
"connect_with_support_team": "ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።",
|
||||
"connect_with_support_team":
|
||||
"ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።",
|
||||
"open_in_telegram": "በቴሌግራም ይክፈቱ",
|
||||
"search_for": "ፈልጉት",
|
||||
"current_level": "የአሁኑ ደረጃ",
|
||||
|
|
@ -187,7 +189,8 @@ class CodegenLoader extends AssetLoader{
|
|||
"evey_one_has_strugle": "ሁሉም ሰው ችግሮች አሉት፣ የአንተን እንጀምር እንፍታ",
|
||||
"write_your_challenge": "ችግርህን ጻፍ…",
|
||||
"topic_interest": "በጣም የሚስቡህ ርዕሶች የትኞቹ ናቸው?",
|
||||
"favourite_topic": "የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።",
|
||||
"favourite_topic":
|
||||
"የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።",
|
||||
"your_interest": "ፍላጎትህን ጻፍ…",
|
||||
"want_quick_assessment": "የእንግሊዝኛ ደረጃህን ለማወቅ ፈጣን ግምገማ ትፈልጋለህ?",
|
||||
"answer_quick_questions": "የእንግሊዝኛ ችሎታህን ለመረዳት ጥቂት ፈጣን ጥያቄዎችን መልስ።",
|
||||
|
|
@ -202,7 +205,8 @@ class CodegenLoader extends AssetLoader{
|
|||
"finish_all_practice_lesson": "ይህን ልምምድ ለመውሰድ የቀድሞውን የትምህርት ልምምድ ያጠናቅቁ",
|
||||
"finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ",
|
||||
"finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ",
|
||||
"finish_all_practice_previouse_module": "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ",
|
||||
"finish_all_practice_previouse_module":
|
||||
"ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ",
|
||||
"finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ",
|
||||
"track_journey": "የትምህርት ጉዞዎን ይከታተሉ እና በጊዜ ሂደት ያሳዩትን እድገት ይመልከቱ።",
|
||||
"learn_english": "እንግሊዝኛ ይማሩ",
|
||||
|
|
@ -210,8 +214,8 @@ class CodegenLoader extends AssetLoader{
|
|||
"completed_practices": "የተጠናቀቁ ልምምዶች",
|
||||
"total_practices": "ጠቅላላ ልምምዶች",
|
||||
"progress_percentage": "የእድገት መቶኛ"
|
||||
};
|
||||
static const Map<String,dynamic> _en = {
|
||||
};
|
||||
static const Map<String, dynamic> _en = {
|
||||
"loading": "Loading",
|
||||
"welcome_back": "Welcome back",
|
||||
"checking_user_info": "Checking user info",
|
||||
|
|
@ -229,13 +233,15 @@ static const Map<String,dynamic> _en = {
|
|||
"login": "Login",
|
||||
"register_with_google": "Register with Google",
|
||||
"register_with_phone": "Register with phone number",
|
||||
"enter_phone_number": "Enter your phone number. We will send you a confirmation code there.",
|
||||
"enter_phone_number":
|
||||
"Enter your phone number. We will send you a confirmation code there.",
|
||||
"login_with_email": "Login with email",
|
||||
"create_password": "Create password",
|
||||
"confirm_password": "Confirm password",
|
||||
"eight_character_minimum": "8 characters minimum",
|
||||
"password_match": "password match",
|
||||
"sign_up_agreement": "By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’",
|
||||
"sign_up_agreement":
|
||||
"By clicking ‘Sign Up’, you agree to our ‘Terms of Service’ and ‘Privacy Policy’",
|
||||
"terms_of_services": "Terms of Service",
|
||||
"and": "and",
|
||||
"privacy_policy": "Privacy Policy",
|
||||
|
|
@ -246,7 +252,8 @@ static const Map<String,dynamic> _en = {
|
|||
"code_sent_to_email": "Code sent to your email",
|
||||
"resend_code_in": "Resend code in",
|
||||
"reset_password": "Reset Password",
|
||||
"enter_email_reset_code": "Enter your email. We will send you a reset code.",
|
||||
"enter_email_reset_code":
|
||||
"Enter your email. We will send you a reset code.",
|
||||
"please_wait": "Please wait",
|
||||
"reset_code_sent": "Reset code sent successfully",
|
||||
"reset_code": "Reset code",
|
||||
|
|
@ -287,7 +294,8 @@ static const Map<String,dynamic> _en = {
|
|||
"cancel": "Cancel",
|
||||
"you_are_speaking": "You're speaking",
|
||||
"practice_completed": "Practice completed!",
|
||||
"great_improvement": "You sound more confident this time, great improvement",
|
||||
"great_improvement":
|
||||
"You sound more confident this time, great improvement",
|
||||
"practice_again": "Practice again",
|
||||
"conversation_review": "Conversation review",
|
||||
"result": "Result",
|
||||
|
|
@ -334,7 +342,8 @@ static const Map<String,dynamic> _en = {
|
|||
"call_our_support": "Call our support team between 9 AM - 6 PM",
|
||||
"tap_to_call": "Tap to call",
|
||||
"join_telegram": "Join Yimaru Academy on Telegram",
|
||||
"connect_with_support_team": "Connect with our support team instantly on Telegram for quick assistance and community updates",
|
||||
"connect_with_support_team":
|
||||
"Connect with our support team instantly on Telegram for quick assistance and community updates",
|
||||
"open_in_telegram": "Open in Telegram",
|
||||
"search_for": "Search for",
|
||||
"current_level": "Current Level",
|
||||
|
|
@ -342,18 +351,22 @@ static const Map<String,dynamic> _en = {
|
|||
"no_practice_available": "No practice available!",
|
||||
"begin_module_practice": "Begin Module Practice",
|
||||
"lets_practice_lesson": "Let’s Practice",
|
||||
"lets_quickly_review": "Let’s quickly review what you’ve learned in this module!",
|
||||
"lets_quickly_review":
|
||||
"Let’s quickly review what you’ve learned in this module!",
|
||||
"lets_practice_module": "Let's practice what you just learnt!",
|
||||
"ask_you_few_actions": "I’ll ask you a few questions, and you can respond naturally.",
|
||||
"ask_you_few_actions":
|
||||
"I’ll ask you a few questions, and you can respond naturally.",
|
||||
"begin_level_practice": "Begin Level Practice",
|
||||
"lets_practice_course": "Let’s Practice Course",
|
||||
"lets_quick_review": "Let’s quickly review what you’ve learned in this level!",
|
||||
"lets_quick_review":
|
||||
"Let’s quickly review what you’ve learned in this level!",
|
||||
"speaking": "is speaking...",
|
||||
"you_have_finished_practice": "You have finished your practice",
|
||||
"view_results": "View My Results",
|
||||
"sample_answer": "Sample Answer",
|
||||
"your_answer": "Your Answer",
|
||||
"sound_confident": "You sound more confident this time - great improvement!",
|
||||
"sound_confident":
|
||||
"You sound more confident this time - great improvement!",
|
||||
"you_have_completed": "Yay, you’ve completed",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
|
|
@ -364,15 +377,20 @@ static const Map<String,dynamic> _en = {
|
|||
"phone_must_start_with": "Phone number must start with 251",
|
||||
"phone_must_be": "Phone number must be 12 digits",
|
||||
"what_should_we_call_you": "What should we call you?",
|
||||
"name_for_personalization": "We’ll use your name to personalize your learning journey.",
|
||||
"name_for_personalization":
|
||||
"We’ll use your name to personalize your learning journey.",
|
||||
"choose_your_gender": "Choose your gender?",
|
||||
"gender_for_personalization": "We’ll personalize your learning experience based on your gender.",
|
||||
"gender_for_personalization":
|
||||
"We’ll personalize your learning experience based on your gender.",
|
||||
"age_range": "Which age range are you in?",
|
||||
"age_for_personalization": "We’ll personalize your learning experience based on your age.",
|
||||
"age_for_personalization":
|
||||
"We’ll personalize your learning experience based on your age.",
|
||||
"educational_background": "What’s your current educational level?",
|
||||
"education_for_personalization": "This helps us tailor your lessons to your experience.",
|
||||
"education_for_personalization":
|
||||
"This helps us tailor your lessons to your experience.",
|
||||
"your_occupation": "What’s your occupation?",
|
||||
"occupation_for_personalization": "We’ll personalize your learning experience based on your occupation.",
|
||||
"occupation_for_personalization":
|
||||
"We’ll personalize your learning experience based on your occupation.",
|
||||
"location": "Where are you from?",
|
||||
"select_country_region": "Select your country and region from the dropdown",
|
||||
"select_country": "Select country",
|
||||
|
|
@ -384,10 +402,13 @@ static const Map<String,dynamic> _en = {
|
|||
"evey_one_has_strugle": "Everyone has struggles, let’s start fixing yours",
|
||||
"write_your_challenge": "Write your challenge…",
|
||||
"topic_interest": "Which topics interest you most?",
|
||||
"favourite_topic": "Your favorite topics help us create fun, relatable lessons.",
|
||||
"favourite_topic":
|
||||
"Your favorite topics help us create fun, relatable lessons.",
|
||||
"your_interest": "Write your interest…",
|
||||
"want_quick_assessment": "Want a quick assessment to know your English level?",
|
||||
"answer_quick_questions": "Answer a few quick questions to help us understand your English proficiency.",
|
||||
"want_quick_assessment":
|
||||
"Want a quick assessment to know your English level?",
|
||||
"answer_quick_questions":
|
||||
"Answer a few quick questions to help us understand your English proficiency.",
|
||||
"skip": "Skip",
|
||||
"finish_level": "Finish Level",
|
||||
"likely_speaker": "You’re likely speaker of",
|
||||
|
|
@ -396,17 +417,26 @@ static const Map<String,dynamic> _en = {
|
|||
"welcome_abroad": "Welcome aboard",
|
||||
"ready_to_explore": "You’re ready to explore your personalized lessons.",
|
||||
"finish": "Finish",
|
||||
"finish_all_practice_lesson": "Finish the previous lesson practice to take this practice",
|
||||
"finish_all_practice_module": "Finish the lesson practices to take the Module Practice",
|
||||
"finish_all_practice_course": "Finish the Module practices to take the Course practice",
|
||||
"finish_all_practice_previouse_module": "Finish the previous Module practice to take this practice",
|
||||
"finish_all_practice_previouse_course": "Finish the previous course practice to take this",
|
||||
"track_journey": "Track your learning journey and see your growth over time.",
|
||||
"finish_all_practice_lesson":
|
||||
"Finish the previous lesson practice to take this practice",
|
||||
"finish_all_practice_module":
|
||||
"Finish the lesson practices to take the Module Practice",
|
||||
"finish_all_practice_course":
|
||||
"Finish the Module practices to take the Course practice",
|
||||
"finish_all_practice_previouse_module":
|
||||
"Finish the previous Module practice to take this practice",
|
||||
"finish_all_practice_previouse_course":
|
||||
"Finish the previous course practice to take this",
|
||||
"track_journey":
|
||||
"Track your learning journey and see your growth over time.",
|
||||
"learn_english": "Learn English",
|
||||
"keep_momentum": "Great job! Keep the momentum.",
|
||||
"completed_practices": "Completed Practices",
|
||||
"total_practices": "Total Practices",
|
||||
"progress_percentage": "Progress Percentage"
|
||||
};
|
||||
static const Map<String, Map<String,dynamic>> mapLocales = {"am": _am, "en": _en};
|
||||
};
|
||||
static const Map<String, Map<String, dynamic>> mapLocales = {
|
||||
"am": _am,
|
||||
"en": _en
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,7 +161,8 @@ abstract class LocaleKeys {
|
|||
static const educational_background = 'educational_background';
|
||||
static const education_for_personalization = 'education_for_personalization';
|
||||
static const your_occupation = 'your_occupation';
|
||||
static const occupation_for_personalization = 'occupation_for_personalization';
|
||||
static const occupation_for_personalization =
|
||||
'occupation_for_personalization';
|
||||
static const location = 'location';
|
||||
static const select_country_region = 'select_country_region';
|
||||
static const select_country = 'select_country';
|
||||
|
|
@ -188,13 +189,14 @@ abstract class LocaleKeys {
|
|||
static const finish_all_practice_lesson = 'finish_all_practice_lesson';
|
||||
static const finish_all_practice_module = 'finish_all_practice_module';
|
||||
static const finish_all_practice_course = 'finish_all_practice_course';
|
||||
static const finish_all_practice_previouse_module = 'finish_all_practice_previouse_module';
|
||||
static const finish_all_practice_previouse_course = 'finish_all_practice_previouse_course';
|
||||
static const finish_all_practice_previouse_module =
|
||||
'finish_all_practice_previouse_module';
|
||||
static const finish_all_practice_previouse_course =
|
||||
'finish_all_practice_previouse_course';
|
||||
static const track_journey = 'track_journey';
|
||||
static const learn_english = 'learn_english';
|
||||
static const keep_momentum = 'keep_momentum';
|
||||
static const completed_practices = 'completed_practices';
|
||||
static const total_practices = 'total_practices';
|
||||
static const progress_percentage = 'progress_percentage';
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ class HomeViewModel extends ReactiveViewModel {
|
|||
rebuildUi();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Remote api calls
|
||||
|
||||
// In-app update
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ class LanguageViewModel extends ReactiveViewModel {
|
|||
rebuildUi();
|
||||
}
|
||||
|
||||
|
||||
// Navigation
|
||||
void pop() => _navigationService.back();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ import 'learn_course_viewmodel.dart';
|
|||
|
||||
class LearnCourseView extends StackedView<LearnCourseViewModel> {
|
||||
final int id;
|
||||
final bool first;
|
||||
|
||||
const LearnCourseView({Key? key, required this.id}) : super(key: key);
|
||||
const LearnCourseView({Key? key, required this.id, required this.first})
|
||||
: super(key: key);
|
||||
|
||||
Future<void> _onPractice(
|
||||
{required BuildContext context,
|
||||
|
|
@ -151,7 +153,9 @@ class LearnCourseView extends StackedView<LearnCourseViewModel> {
|
|||
viewModel: viewModel,
|
||||
course: viewModel.courses[index]),
|
||||
onViewTap: () async =>
|
||||
await viewModel.navigateToLearnModule(viewModel.courses[index]),
|
||||
await viewModel.navigateToLearnModule(
|
||||
first: first && index ==0,
|
||||
course: viewModel.courses[index]),
|
||||
),
|
||||
separatorBuilder: (context, index) => verticalSpaceSmall,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ class LearnCourseViewModel extends ReactiveViewModel {
|
|||
Future<void> navigateToLearnSubscription() async =>
|
||||
await _navigationService.navigateToLearnSubscriptionView();
|
||||
|
||||
Future<void> navigateToLearnModule(LearnCourse course) async =>
|
||||
_navigationService.navigateToLearnModuleView(course: course);
|
||||
Future<void> navigateToLearnModule({required bool first,required LearnCourse course}) async =>
|
||||
_navigationService.navigateToLearnModuleView(first: first,course: course);
|
||||
|
||||
Future<void> navigateToLearnPractice(
|
||||
{required int id, required String level}) async =>
|
||||
|
|
|
|||
|
|
@ -17,21 +17,17 @@ import '../../widgets/small_app_bar.dart';
|
|||
import 'learn_lesson_viewmodel.dart';
|
||||
|
||||
class LearnLessonView extends StackedView<LearnLessonViewModel> {
|
||||
final bool first;
|
||||
final LearnModule module;
|
||||
|
||||
const LearnLessonView({Key? key, required this.module}) : super(key: key);
|
||||
const LearnLessonView({Key? key, required this.first, required this.module})
|
||||
: super(key: key);
|
||||
|
||||
Future<void> _onPractice(
|
||||
{required int index,
|
||||
required LearnLesson lesson,
|
||||
required BuildContext context,
|
||||
required LearnLessonViewModel viewModel}) async {
|
||||
/* if (lesson.access?.isAccessible ?? false) {
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
} else {
|
||||
await _showSheet(context: context, viewModel: viewModel);
|
||||
}*/
|
||||
if (index > 1) {
|
||||
if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'active') {
|
||||
if (lesson.access?.isAccessible ?? false) {
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
|
|
@ -39,10 +35,7 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
|
|||
await _showSheet(context: context, viewModel: viewModel);
|
||||
}
|
||||
} else {
|
||||
await viewModel.navigateToLearnSubscription();
|
||||
}
|
||||
} else {
|
||||
if (lesson.access?.isAccessible ?? false) {
|
||||
if (first && index < 3) {
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
} else {
|
||||
await _showSheet(context: context, viewModel: viewModel);
|
||||
|
|
@ -224,6 +217,7 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
|
|||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) => _buildTile(
|
||||
index: index,
|
||||
first: first && index < 3,
|
||||
lesson: viewModel.lessons[index],
|
||||
last: index == viewModel.lessons.length - 1,
|
||||
onPracticeTap: () async => await _onPractice(
|
||||
|
|
@ -244,12 +238,14 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
|
|||
Widget _buildTile({
|
||||
required bool last,
|
||||
required int index,
|
||||
required bool first,
|
||||
required LearnLesson lesson,
|
||||
required GestureTapCallback? onLessonTap,
|
||||
required GestureTapCallback? onPracticeTap,
|
||||
}) =>
|
||||
LearnLessonTile(
|
||||
last: last,
|
||||
first: first,
|
||||
index: index,
|
||||
lesson: lesson,
|
||||
onLessonTap: onLessonTap,
|
||||
|
|
|
|||
|
|
@ -31,21 +31,9 @@ class LearnLessonDetailView extends StackedView<LearnLessonDetailViewModel> {
|
|||
Future<void> _onPractice(
|
||||
{required LearnLesson lesson,
|
||||
required LearnLessonDetailViewModel viewModel}) async {
|
||||
/* await viewModel.pause();
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
*/
|
||||
if (index > 1) {
|
||||
if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'active') {
|
||||
await viewModel.pause();
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
} else {
|
||||
await viewModel.pause();
|
||||
await viewModel.navigateToLearnSubscription();
|
||||
}
|
||||
} else {
|
||||
await viewModel.pause();
|
||||
await viewModel.navigateToLearnPractice(lesson.id ?? 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -16,9 +16,11 @@ import '../../widgets/small_app_bar.dart';
|
|||
import 'learn_module_viewmodel.dart';
|
||||
|
||||
class LearnModuleView extends StackedView<LearnModuleViewModel> {
|
||||
final bool first;
|
||||
final LearnCourse course;
|
||||
|
||||
const LearnModuleView({Key? key, required this.course}) : super(key: key);
|
||||
const LearnModuleView({Key? key, required this.first, required this.course})
|
||||
: super(key: key);
|
||||
|
||||
Future<void> _onPractice(
|
||||
{required BuildContext context,
|
||||
|
|
@ -202,7 +204,9 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
|
|||
module: viewModel.modules[index],
|
||||
),
|
||||
onModuleTap: () async =>
|
||||
await viewModel.navigateToLearnLesson(viewModel.modules[index]),
|
||||
await viewModel.navigateToLearnLesson(
|
||||
first: first && index == 0,
|
||||
module: viewModel.modules[index]),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class LearnModuleViewModel extends ReactiveViewModel {
|
|||
// Navigation
|
||||
void pop() => _navigationService.back();
|
||||
|
||||
Future<void> navigateToLearnLesson(LearnModule module) async =>
|
||||
await _navigationService.navigateToLearnLessonView(module: module);
|
||||
Future<void> navigateToLearnLesson({required bool first, required LearnModule module}) async =>
|
||||
await _navigationService.navigateToLearnLessonView(first:first,module: module);
|
||||
|
||||
Future<void> navigateToLearnPractice(
|
||||
{required int id, required String module}) async =>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:yimaru_app/services/voice_recorder_service.dart';
|
|||
import 'package:yimaru_app/ui/common/enmus.dart';
|
||||
|
||||
import '../../../app/app.locator.dart';
|
||||
import '../../../app/app.router.dart';
|
||||
import '../../../models/learn_question.dart';
|
||||
import '../../../services/api_service.dart';
|
||||
import '../../../services/audio_player_service.dart';
|
||||
|
|
@ -264,6 +265,9 @@ class LearnPracticeViewModel extends ReactiveViewModel {
|
|||
// Navigation
|
||||
void pop() => _navigationService.back();
|
||||
|
||||
Future<void> navigateToLearnSubscription() async =>
|
||||
await _navigationService.navigateToLearnSubscriptionView();
|
||||
|
||||
// Remote api call
|
||||
|
||||
// Refresh url
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
|
|||
required this.subtitle,
|
||||
required this.practice});
|
||||
|
||||
Future<void> _practice(LearnPracticeViewModel viewModel) async {
|
||||
if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'active') {
|
||||
viewModel.goTo(1);
|
||||
} else {
|
||||
await viewModel.navigateToLearnSubscription();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _cancel(LearnPracticeViewModel viewModel) async {
|
||||
await viewModel.stopRecording();
|
||||
viewModel.pop();
|
||||
|
|
@ -207,7 +215,7 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
|
|||
text: label,
|
||||
borderRadius: 12,
|
||||
foregroundColor: kcWhite,
|
||||
onTap: () => viewModel.goTo(1),
|
||||
backgroundColor: kcPrimaryColor,
|
||||
onTap: () async => await _practice(viewModel),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ class LearnProgramView extends StackedView<LearnProgramViewModel> {
|
|||
separatorBuilder: (context, index) => verticalSpaceSmall,
|
||||
itemBuilder: (context, index) => _buildTile(
|
||||
program: viewModel.learnPrograms[index],
|
||||
onTap: () async => await viewModel
|
||||
.navigateToLearnCourse(viewModel.learnPrograms[index].id ?? 0),
|
||||
onTap: () async => await viewModel.navigateToLearnCourse(
|
||||
first: index == 0, id: viewModel.learnPrograms[index].id ?? 0),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ class LearnProgramViewModel extends ReactiveViewModel {
|
|||
List<LearnProgram> get learnPrograms => _learnPrograms;
|
||||
|
||||
// Navigation
|
||||
Future<void> navigateToLearnCourse(int id) async =>
|
||||
_navigationService.navigateToLearnCourseView(id: id);
|
||||
Future<void> navigateToLearnCourse({required int id,required bool first}) async =>
|
||||
_navigationService.navigateToLearnCourseView(id: id,first: first);
|
||||
|
||||
// Remote api call
|
||||
|
||||
|
|
|
|||
|
|
@ -205,8 +205,8 @@ class OnboardingViewModel extends ReactiveViewModel
|
|||
_selectedCountry = value;
|
||||
if (value?.code?.toLowerCase().trim() == 'et') {
|
||||
_dropdownRegion = true;
|
||||
_selectedRegion = _regions
|
||||
.firstWhere((e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false);
|
||||
_selectedRegion = _regions.firstWhere(
|
||||
(e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false);
|
||||
} else {
|
||||
_dropdownRegion = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ class PaymentView extends StackedView<PaymentViewModel> {
|
|||
|
||||
@override
|
||||
void onViewModelReady(PaymentViewModel viewModel) async {
|
||||
await viewModel.createLearnSubscriptionRequest(phone: phone,subscription: subscription);
|
||||
await viewModel.createLearnSubscriptionRequest(
|
||||
phone: phone, subscription: subscription);
|
||||
super.onViewModelReady(viewModel);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,18 +45,22 @@ class PaymentViewModel extends ReactiveViewModel {
|
|||
// Remote api call
|
||||
|
||||
// Learn subscription
|
||||
Future<void> createLearnSubscriptionRequest({required String phone,required LearnSubscription subscription}) async =>
|
||||
await runBusyFuture(_createLearnSubscriptionRequest(phone: phone,subscription: subscription),
|
||||
Future<void> createLearnSubscriptionRequest(
|
||||
{required String phone,
|
||||
required LearnSubscription subscription}) async =>
|
||||
await runBusyFuture(
|
||||
_createLearnSubscriptionRequest(
|
||||
phone: phone, subscription: subscription),
|
||||
busyObject: StateObjects.learnSubscription);
|
||||
|
||||
Future<void> _createLearnSubscriptionRequest({required String phone,required LearnSubscription subscription}) async {
|
||||
Future<void> _createLearnSubscriptionRequest(
|
||||
{required String phone, required LearnSubscription subscription}) async {
|
||||
if (await _statusChecker.checkConnection()) {
|
||||
Map<String, dynamic> data = {
|
||||
'provider': 'CHAPA',
|
||||
'phone': '251$phone',
|
||||
'email': 'test@gmail.com',
|
||||
'plan_id': subscription.id,
|
||||
|
||||
};
|
||||
|
||||
Map<String, dynamic> response =
|
||||
|
|
|
|||
|
|
@ -136,8 +136,8 @@ class ProfileDetailViewModel extends ReactiveViewModel
|
|||
|
||||
void setEthiopianRegion(String region) {
|
||||
_dropdownRegion = true;
|
||||
_selectedRegion =
|
||||
_regions.firstWhere((r) => r.code?.toLowerCase() == region.toLowerCase());
|
||||
_selectedRegion = _regions
|
||||
.firstWhere((r) => r.code?.toLowerCase() == region.toLowerCase());
|
||||
|
||||
rebuildUi();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class ProgressViewModel extends ReactiveViewModel {
|
|||
@override
|
||||
List<ListenableServiceMixin> get listenableServices => [_learnService];
|
||||
|
||||
|
||||
// Total practice count
|
||||
int get _totalCount => _learnService.totalCount;
|
||||
|
||||
|
|
@ -33,7 +32,6 @@ class ProgressViewModel extends ReactiveViewModel {
|
|||
|
||||
int get totalProgress => _totalProgress;
|
||||
|
||||
|
||||
// Courses
|
||||
final List<Map<String, dynamic>> _courses = [
|
||||
{
|
||||
|
|
@ -53,7 +51,8 @@ class ProgressViewModel extends ReactiveViewModel {
|
|||
|
||||
// Learning progress
|
||||
|
||||
Future<void> getProgressSummary() async => runBusyFuture(_getProgressSummary(),
|
||||
Future<void> getProgressSummary() async =>
|
||||
runBusyFuture(_getProgressSummary(),
|
||||
busyObject: StateObjects.progressSummary);
|
||||
|
||||
Future<void> _getProgressSummary() async {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import 'custom_linear_progress_indicator.dart';
|
|||
class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
||||
final int index;
|
||||
final bool last;
|
||||
final bool first;
|
||||
final LearnLesson lesson;
|
||||
final GestureTapCallback? onLessonTap;
|
||||
final GestureTapCallback? onPracticeTap;
|
||||
|
|
@ -26,6 +27,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
this.onLessonTap,
|
||||
this.onPracticeTap,
|
||||
required this.last,
|
||||
required this.first,
|
||||
required this.index,
|
||||
required this.lesson});
|
||||
|
||||
|
|
@ -35,7 +37,9 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
|
||||
Widget _buildContainerWrapper(LearnLessonViewModel viewModel) =>
|
||||
GestureDetector(
|
||||
onTap: !(lesson.access?.isAccessible ?? false) ? onPracticeTap : null,
|
||||
onTap: viewModel.user?.subscriptionStatus?.toLowerCase() == 'active' ? !(lesson.access?.isAccessible ?? false)
|
||||
? onPracticeTap
|
||||
: null: !first ? onPracticeTap:null,
|
||||
child: _buildContainer(viewModel),
|
||||
);
|
||||
|
||||
|
|
@ -56,7 +60,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
Widget _buildTileStack(LearnLessonViewModel viewModel) => Stack(
|
||||
children: [
|
||||
_buildExpansionTile(viewModel),
|
||||
_buildContainerShaderState()
|
||||
_buildContainerShaderState(viewModel)
|
||||
],
|
||||
);
|
||||
|
||||
|
|
@ -70,7 +74,6 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
shape: Border.all(color: kcTransparent),
|
||||
expandedAlignment: Alignment.centerLeft,
|
||||
leading: _buildLeadingWrapper(viewModel),
|
||||
enabled: (lesson.access?.isAccessible ?? false),
|
||||
controlAffinity: ListTileControlAffinity.trailing,
|
||||
expandedCrossAxisAlignment: CrossAxisAlignment.start,
|
||||
tilePadding: const EdgeInsets.fromLTRB(15, 15, 15, 15),
|
||||
|
|
@ -85,6 +88,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
collapsedBackgroundColor: (lesson.access?.isCompleted ?? false)
|
||||
? kcGreen.withOpacity(0.1)
|
||||
: kcPrimaryColor.withOpacity(0.1),
|
||||
enabled: first ? true : (lesson.access?.isAccessible ?? false),
|
||||
children: _buildExpansionTileChildren(viewModel),
|
||||
);
|
||||
|
||||
|
|
@ -203,7 +207,12 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
|
|||
backgroundColor: kcPrimaryColor,
|
||||
);
|
||||
|
||||
Widget _buildContainerShaderState() => !(lesson.access?.isAccessible ?? false)
|
||||
Widget _buildContainerShaderState(LearnLessonViewModel viewModel) =>
|
||||
viewModel.user?.subscriptionStatus?.toLowerCase() == 'active'
|
||||
? !(lesson.access?.isAccessible ?? false)
|
||||
? _buildContainerShader()
|
||||
: Container()
|
||||
: !first
|
||||
? _buildContainerShader()
|
||||
: Container();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name: yimaru_app
|
||||
publish_to: 'none'
|
||||
version: 0.1.33+35
|
||||
version: 0.1.34+36
|
||||
description: A new Flutter project.
|
||||
|
||||
environment:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user