Merge branch 'release/0.1.34'

-fix(subscription): Subscription logic updated
This commit is contained in:
BisratHailu 2026-06-03 03:48:00 +03:00
commit 2554b80359
28 changed files with 558 additions and 498 deletions

View File

@ -475,16 +475,16 @@ class StackedRouter extends _i1.RouterBase {
_i18.LearnModuleView: (data) { _i18.LearnModuleView: (data) {
final args = data.getArgs<LearnModuleViewArguments>(nullOk: false); final args = data.getArgs<LearnModuleViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>( return _i37.MaterialPageRoute<dynamic>(
builder: (context) => builder: (context) => _i18.LearnModuleView(
_i18.LearnModuleView(key: args.key, course: args.course), key: args.key, first: args.first, course: args.course),
settings: data, settings: data,
); );
}, },
_i19.LearnLessonView: (data) { _i19.LearnLessonView: (data) {
final args = data.getArgs<LearnLessonViewArguments>(nullOk: false); final args = data.getArgs<LearnLessonViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>( return _i37.MaterialPageRoute<dynamic>(
builder: (context) => builder: (context) => _i19.LearnLessonView(
_i19.LearnLessonView(key: args.key, module: args.module), key: args.key, first: args.first, module: args.module),
settings: data, settings: data,
); );
}, },
@ -628,7 +628,8 @@ class StackedRouter extends _i1.RouterBase {
_i35.LearnCourseView: (data) { _i35.LearnCourseView: (data) {
final args = data.getArgs<LearnCourseViewArguments>(nullOk: false); final args = data.getArgs<LearnCourseViewArguments>(nullOk: false);
return _i37.MaterialPageRoute<dynamic>( 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, settings: data,
); );
}, },
@ -1009,54 +1010,60 @@ class LoginViewArguments {
class LearnModuleViewArguments { class LearnModuleViewArguments {
const LearnModuleViewArguments({ const LearnModuleViewArguments({
this.key, this.key,
required this.first,
required this.course, required this.course,
}); });
final _i37.Key? key; final _i37.Key? key;
final bool first;
final _i38.LearnCourse course; final _i38.LearnCourse course;
@override @override
String toString() { String toString() {
return '{"key": "$key", "course": "$course"}'; return '{"key": "$key", "first": "$first", "course": "$course"}';
} }
@override @override
bool operator ==(covariant LearnModuleViewArguments other) { bool operator ==(covariant LearnModuleViewArguments other) {
if (identical(this, other)) return true; if (identical(this, other)) return true;
return other.key == key && other.course == course; return other.key == key && other.first == first && other.course == course;
} }
@override @override
int get hashCode { int get hashCode {
return key.hashCode ^ course.hashCode; return key.hashCode ^ first.hashCode ^ course.hashCode;
} }
} }
class LearnLessonViewArguments { class LearnLessonViewArguments {
const LearnLessonViewArguments({ const LearnLessonViewArguments({
this.key, this.key,
required this.first,
required this.module, required this.module,
}); });
final _i37.Key? key; final _i37.Key? key;
final bool first;
final _i39.LearnModule module; final _i39.LearnModule module;
@override @override
String toString() { String toString() {
return '{"key": "$key", "module": "$module"}'; return '{"key": "$key", "first": "$first", "module": "$module"}';
} }
@override @override
bool operator ==(covariant LearnLessonViewArguments other) { bool operator ==(covariant LearnLessonViewArguments other) {
if (identical(this, other)) return true; if (identical(this, other)) return true;
return other.key == key && other.module == module; return other.key == key && other.first == first && other.module == module;
} }
@override @override
int get hashCode { int get hashCode {
return key.hashCode ^ module.hashCode; return key.hashCode ^ first.hashCode ^ module.hashCode;
} }
} }
@ -1486,26 +1493,29 @@ class LearnCourseViewArguments {
const LearnCourseViewArguments({ const LearnCourseViewArguments({
this.key, this.key,
required this.id, required this.id,
required this.first,
}); });
final _i37.Key? key; final _i37.Key? key;
final int id; final int id;
final bool first;
@override @override
String toString() { String toString() {
return '{"key": "$key", "id": "$id"}'; return '{"key": "$key", "id": "$id", "first": "$first"}';
} }
@override @override
bool operator ==(covariant LearnCourseViewArguments other) { bool operator ==(covariant LearnCourseViewArguments other) {
if (identical(this, other)) return true; if (identical(this, other)) return true;
return other.key == key && other.id == id; return other.key == key && other.id == id && other.first == first;
} }
@override @override
int get hashCode { 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({ Future<dynamic> navigateToLearnModuleView({
_i37.Key? key, _i37.Key? key,
required bool first,
required _i38.LearnCourse course, required _i38.LearnCourse course,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
@ -1809,7 +1820,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return navigateTo<dynamic>(Routes.learnModuleView, return navigateTo<dynamic>(Routes.learnModuleView,
arguments: LearnModuleViewArguments(key: key, course: course), arguments:
LearnModuleViewArguments(key: key, first: first, course: course),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -1818,6 +1830,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
Future<dynamic> navigateToLearnLessonView({ Future<dynamic> navigateToLearnLessonView({
_i37.Key? key, _i37.Key? key,
required bool first,
required _i39.LearnModule module, required _i39.LearnModule module,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
@ -1826,7 +1839,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return navigateTo<dynamic>(Routes.learnLessonView, return navigateTo<dynamic>(Routes.learnLessonView,
arguments: LearnLessonViewArguments(key: key, module: module), arguments:
LearnLessonViewArguments(key: key, first: first, module: module),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -2107,6 +2121,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
Future<dynamic> navigateToLearnCourseView({ Future<dynamic> navigateToLearnCourseView({
_i37.Key? key, _i37.Key? key,
required int id, required int id,
required bool first,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
@ -2114,7 +2129,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return navigateTo<dynamic>(Routes.learnCourseView, return navigateTo<dynamic>(Routes.learnCourseView,
arguments: LearnCourseViewArguments(key: key, id: id), arguments: LearnCourseViewArguments(key: key, id: id, first: first),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -2399,6 +2414,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
Future<dynamic> replaceWithLearnModuleView({ Future<dynamic> replaceWithLearnModuleView({
_i37.Key? key, _i37.Key? key,
required bool first,
required _i38.LearnCourse course, required _i38.LearnCourse course,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
@ -2407,7 +2423,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return replaceWith<dynamic>(Routes.learnModuleView, return replaceWith<dynamic>(Routes.learnModuleView,
arguments: LearnModuleViewArguments(key: key, course: course), arguments:
LearnModuleViewArguments(key: key, first: first, course: course),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -2416,6 +2433,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
Future<dynamic> replaceWithLearnLessonView({ Future<dynamic> replaceWithLearnLessonView({
_i37.Key? key, _i37.Key? key,
required bool first,
required _i39.LearnModule module, required _i39.LearnModule module,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
@ -2424,7 +2442,8 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return replaceWith<dynamic>(Routes.learnLessonView, return replaceWith<dynamic>(Routes.learnLessonView,
arguments: LearnLessonViewArguments(key: key, module: module), arguments:
LearnLessonViewArguments(key: key, first: first, module: module),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,
@ -2705,6 +2724,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
Future<dynamic> replaceWithLearnCourseView({ Future<dynamic> replaceWithLearnCourseView({
_i37.Key? key, _i37.Key? key,
required int id, required int id,
required bool first,
int? routerId, int? routerId,
bool preventDuplicates = true, bool preventDuplicates = true,
Map<String, String>? parameters, Map<String, String>? parameters,
@ -2712,7 +2732,7 @@ extension NavigatorStateExtension on _i47.NavigationService {
transition, transition,
}) async { }) async {
return replaceWith<dynamic>(Routes.learnCourseView, return replaceWith<dynamic>(Routes.learnCourseView,
arguments: LearnCourseViewArguments(key: key, id: id), arguments: LearnCourseViewArguments(key: key, id: id, first: first),
id: routerId, id: routerId,
preventDuplicates: preventDuplicates, preventDuplicates: preventDuplicates,
parameters: parameters, parameters: parameters,

View File

@ -23,7 +23,7 @@ class AuthenticationService with ListenableServiceMixin {
// Initialization // Initialization
AuthenticationService() { AuthenticationService() {
listenToReactiveValues([_user,_state, _localizationService]); listenToReactiveValues([_user, _state, _localizationService]);
} }
// Logout state // Logout state
@ -31,7 +31,6 @@ class AuthenticationService with ListenableServiceMixin {
StateObjects get state => _state; StateObjects get state => _state;
// Check user logged in // Check user logged in
Future<bool> userLoggedIn() async { Future<bool> userLoggedIn() async {
if (await _secureService.getString('userId') != null) { if (await _secureService.getString('userId') != null) {
@ -202,7 +201,6 @@ class AuthenticationService with ListenableServiceMixin {
await setFirstTimeInstall(firstTimeInstall); await setFirstTimeInstall(firstTimeInstall);
await _secureService.setString('language', language); await _secureService.setString('language', language);
_state = StateObjects.none; _state = StateObjects.none;
notifyListeners(); notifyListeners();
} }

View File

@ -29,7 +29,6 @@ class GoogleAuthService with ListenableServiceMixin {
_googleUser ??= _googleUser ??=
await _signIn.authenticate(scopeHint: ['email', 'profile']); await _signIn.authenticate(scopeHint: ['email', 'profile']);
}); });
notifyListeners(); notifyListeners();
} catch (e) { } catch (e) {

View File

@ -58,8 +58,6 @@ class LearnService with ListenableServiceMixin {
List<LearnLesson> get lessons => _lessons; List<LearnLesson> get lessons => _lessons;
// Learn programs // Learn programs
Future<String?> refreshObject(String url) async { Future<String?> refreshObject(String url) async {
Map<String, dynamic> data = {'reference': url}; Map<String, dynamic> data = {'reference': url};

View File

@ -124,5 +124,4 @@ String kTelegramSupportLink = 'https://t.me/yimaruacademy2026';
String kErrorUrl = 'https://api.yimaruacademy.com/payment/error'; String kErrorUrl = 'https://api.yimaruacademy.com/payment/error';
String kSuccessUrl = String kSuccessUrl = 'https://api.yimaruacademy.com/payment/success';
'https://api.yimaruacademy.com/payment/success';

View File

@ -6,7 +6,7 @@ import 'dart:ui';
import 'package:easy_localization/easy_localization.dart' show AssetLoader; import 'package:easy_localization/easy_localization.dart' show AssetLoader;
class CodegenLoader extends AssetLoader{ class CodegenLoader extends AssetLoader {
const CodegenLoader(); const CodegenLoader();
@override @override
@ -14,399 +14,429 @@ class CodegenLoader extends AssetLoader{
return Future.value(mapLocales[locale.toString()]); return Future.value(mapLocales[locale.toString()]);
} }
static const Map<String,dynamic> _am = { static const Map<String, dynamic> _am = {
"loading": "በመጫን ላይ", "loading": "በመጫን ላይ",
"welcome_back": "እንኳን በደህና ተመለሱ", "welcome_back": "እንኳን በደህና ተመለሱ",
"checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ", "checking_user_info": "የተጠቃሚ መረጃን በማረጋገጥ ላይ",
"dont_have_account": "መለያ የለዎትም?", "dont_have_account": "መለያ የለዎትም?",
"email": "ኢሜይል", "email": "ኢሜይል",
"password": "የይለፍ ቃል", "password": "የይለፍ ቃል",
"forgot_password": "የይለፍ ቃል ረሱ?", "forgot_password": "የይለፍ ቃል ረሱ?",
"cont": "ቀጥል", "cont": "ቀጥል",
"register": "ይመዝገቡ", "register": "ይመዝገቡ",
"login_with_google": "በጉግል ይግቡ", "login_with_google": "በጉግል ይግቡ",
"or": "ወይም", "or": "ወይም",
"login_with_phone": "በስልክ ቁጥር ይግቡ", "login_with_phone": "በስልክ ቁጥር ይግቡ",
"create_account": "አዲስ መለያ ይፍጠሩ", "create_account": "አዲስ መለያ ይፍጠሩ",
"already_have_account": "መለያ አለዎት?", "already_have_account": "መለያ አለዎት?",
"login": " ይግቡ ", "login": " ይግቡ ",
"register_with_google": "በጉግል ይመዝገቡ", "register_with_google": "በጉግል ይመዝገቡ",
"register_with_phone": "በስልክ ቁጥር ይመዝገቡ", "register_with_phone": "በስልክ ቁጥር ይመዝገቡ",
"enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።", "enter_phone_number": "የስልክ ቁጥርዎን ያስገቡ። የማረጋገጫ ኮድ እንልክልዎታለን።",
"login_with_email": "በኢሜይል ይግቡ", "login_with_email": "በኢሜይል ይግቡ",
"create_password": "የይለፍ ቃል ይፍጠሩ", "create_password": "የይለፍ ቃል ይፍጠሩ",
"confirm_password": "የይለፍ ቃል ያረጋግጡ", "confirm_password": "የይለፍ ቃል ያረጋግጡ",
"eight_character_minimum": "ቢያንስ 8 ፊደላት", "eight_character_minimum": "ቢያንስ 8 ፊደላት",
"password_match": "የይለፍ ቃሉ ተመሳስሏል", "password_match": "የይለፍ ቃሉ ተመሳስሏል",
"sign_up_agreement": "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።", "sign_up_agreement":
"terms_of_services": "የአገልግሎት ውሎች", "‘ይመዝገቡ’ የሚለውን ሲጫኑ በ‘አገልግሎት ውሎች’ እና ‘በግላዊነት ፖሊሲ’ ይስማማሉ።",
"and": "እና", "terms_of_services": "የአገልግሎት ውሎች",
"privacy_policy": "የግላዊነት ፖሊሲ", "and": "እና",
"register_with_email": "በኢሜል ይመዝገቡ", "privacy_policy": "የግላዊነት ፖሊሲ",
"verification_code": "የማረጋገጫ ኮድ", "register_with_email": "በኢሜል ይመዝገቡ",
"resend_code": "ኮዱን እንደገና ላክ", "verification_code": "የማረጋገጫ ኮድ",
"code_sent_to_phone": "ኮዱ ወደ ስልክ ቁጥርዎ ተልኳል", "resend_code": "ኮዱን እንደገና ላክ",
"code_sent_to_email": "ኮዱ ወደ ኢሜል ተልኳል", "code_sent_to_phone": "ኮዱ ወደ ስልክ ቁጥርዎ ተልኳል",
"resend_code_in": "ኮዱን እንደገና ለመላክ የቀረው ጊዜ", "code_sent_to_email": "ኮዱ ወደ ኢሜል ተልኳል",
"reset_password": " የይለፍ ቃልን ይቀይሩ", "resend_code_in": "ኮዱን እንደገና ለመላክ የቀረው ጊዜ",
"enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።", "reset_password": " የይለፍ ቃልን ይቀይሩ",
"please_wait": "እባክዎ ይጠብቁ", "enter_email_reset_code": "ኢሜይልዎን ያስገቡ። የይለፍ ቃል መለወጫ ኮድ እንልክልዎታለን።",
"reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል", "please_wait": "እባክዎ ይጠብቁ",
"reset_code": " የመቀየሪያ ኮድ ", "reset_code_sent": "የመቀየሪያ ኮድ በተሳካ ሁኔታ ተልኳል",
"new_password": "አዲስ የይለፍ ቃል", "reset_code": " የመቀየሪያ ኮድ ",
"logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል", "new_password": "አዲስ የይለፍ ቃል",
"view_course": " ኮርሱን ይመልከቱ", "logged_in_successfully": "በተሳካ ሁኔታ ገብተዋል",
"continue_learning": "መማርን ይቀጥሉ", "view_course": " ኮርሱን ይመልከቱ",
"start_learning": "ትምህርትን ይጀምሩ", "continue_learning": "መማርን ይቀጥሉ",
"completed": "ተጠናቋል", "start_learning": "ትምህርትን ይጀምሩ",
"take_practice": "ልምምድ ያድርጉ", "completed": "ተጠናቋል",
"your_current_level": "የአሁኑ ደረጃዎ", "take_practice": "ልምምድ ያድርጉ",
"overall_progress": "አጠቃላይ እድገት", "your_current_level": "የአሁኑ ደረጃዎ",
"great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው", "overall_progress": "አጠቃላይ እድገት",
"view_module": "ሞጁሉን ይመልከቱ", "great_work": "በርቱ! በጣም ጥሩ እየሰሩ ነው",
"progress": "እድገት", "view_module": "ሞጁሉን ይመልከቱ",
"keep_going": "ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ", "progress": "እድገት",
"lessons_in_module": "በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ", "keep_going": "ይቀጥሉ - ከግማሽ በላይ ጨርሰዋል ",
"practice": "ልምምድ", "lessons_in_module": "በዚህ ሞጁል ውስጥ ያሉ ትምህርቶች ",
"start": "ጀምር", "practice": "ልምምድ",
"in_progress": "በሂደት ላይ", "start": "ጀምር",
"hello": "ሰላም", "in_progress": "በሂደት ላይ",
"ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ", "hello": "ሰላም",
"learn": "ይማሩ ", "ready_to_learn": " ዛሬ እንግሊዝኛ ለመማር ተዘጋጅተዋል? ",
"course": "ኮርስ", "learn": "ይማሩ ",
"profile": " ፕሮፋይል ", "course": "ኮርስ",
"speaking_partner": "የንግግር ጓደኛ", "profile": " ፕሮፋይል ",
"practice_what_you_learned": "አሁን የተማሩትን እንለማመድ", "speaking_partner": "የንግግር ጓደኛ",
"practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ", "practice_what_you_learned": "አሁን የተማሩትን እንለማመድ",
"start_practice": "ልምምድ ጀምር", "practice_questions": "ጥቂት ጥያቄዎችን እጠይቃለሁ እና መልስ መስጠት ይችላሉ",
"almost_there": "ሊጨርሱ ተቃርበዋል", "start_practice": "ልምምድ ጀምር",
"finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ", "almost_there": "ሊጨርሱ ተቃርበዋል",
"continue_practice": "ልምምዱን ይቀጥሉ", "finish_session": "እድገትዎን ለማየት ክፍለ ጊዜውን ያጠናቅቁ",
"end_session": "ክፍለ ጊዜውን ያብቁ ", "continue_practice": "ልምምዱን ይቀጥሉ",
"tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ", "end_session": "ክፍለ ጊዜውን ያብቁ ",
"practice_speaking": "ንግግርን ይለማመዱ", "tap_start_to_listen": "ለማዳመጥ የጀምር ቁልፉን ይጫኑ",
"tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ", "practice_speaking": "ንግግርን ይለማመዱ",
"reply": "እንደገና አዳምጥ", "tap_microphone": "ለመናገር ማይክሮፎኑን ይጫኑ",
"cancel": "ይቅር", "reply": "እንደገና አዳምጥ",
"you_are_speaking": "እየተናገሩ ነው", "cancel": "ይቅር",
"practice_completed": "ልምምዱ ተጠናቅቋል", "you_are_speaking": "እየተናገሩ ነው",
"great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው", "practice_completed": "ልምምዱ ተጠናቅቋል",
"practice_again": "እንደገና ይለማመዱ", "great_improvement": "በዚህኛው በራስ መተማመንዎ ጨምሯል፤ ትልቅ መሻሻል ነው",
"conversation_review": "የንግግር ግምገማ", "practice_again": "እንደገና ይለማመዱ",
"result": "ውጤት", "conversation_review": "የንግግር ግምገማ",
"quick_tip": "ጠቃሚ ምክር", "result": "ውጤት",
"retry": "እንደገና ይሞክሩ", "quick_tip": "ጠቃሚ ምክር",
"completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል", "retry": "እንደገና ይሞክሩ",
"analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው", "completed_a1": "እንኳን ደስ አለዎት! A1 ደረጃን አጠናቅቀዋል",
"view_profile": "ፕሮፋይሎን ይመልከቱ ", "analyzing_speaking": "የንግግር ችሎታዎን እየገመገምን ነው",
"hi": "ሰላም", "view_profile": "ፕሮፋይሎን ይመልከቱ ",
"edit_profile": "መገለጫ ያስተካክሉ", "hi": "ሰላም",
"first_name": "የመጀመሪያ ስም", "edit_profile": "መገለጫ ያስተካክሉ",
"last_name": "የአባት ስም", "first_name": "የመጀመሪያ ስም",
"gender": "ፆታ", "last_name": "የአባት ስም",
"male": "ወንድ", "gender": "ፆታ",
"female": "ሴት", "male": "ወንድ",
"phone_number": "የስልክ ቁጥር", "female": "ሴት",
"country": "ሀገር", "phone_number": "የስልክ ቁጥር",
"region": "ክልል", "country": "ሀገር",
"select_region": "ክልል ይምረጡ", "region": "ክልል",
"enter_your_city": "ከተማዎን ያስገቡ", "select_region": "ክልል ይምረጡ",
"occupation": "የስራ መስክ", "enter_your_city": "ከተማዎን ያስገቡ",
"select_occupation": "ሙያዎን ይምረጡ", "occupation": "የስራ መስክ",
"save_changes": "ለውጦችን ያስቀምጡ", "select_occupation": "ሙያዎን ይምረጡ",
"my_progress": "የእኔ እድገት", "save_changes": "ለውጦችን ያስቀምጡ",
"track_your_achievement": "ስኬቶችዎን እና ተከታታይ የትምህርት ጉዞዎን ይከታተሉ", "my_progress": "የእኔ እድገት",
"account_and_privacy": "መለያ እና ግላዊነት", "track_your_achievement": "ስኬቶችዎን እና ተከታታይ የትምህርት ጉዞዎን ይከታተሉ",
"manage_settings": "ቅንብሮችን እና የመተግበሪያ ምርጫዎችን ያስተዳድሩ", "account_and_privacy": "መለያ እና ግላዊነት",
"support": "ድጋፍ", "manage_settings": "ቅንብሮችን እና የመተግበሪያ ምርጫዎችን ያስተዳድሩ",
"get_help": "በስልክ ወይም በቴሌግራም እገዛ ያግኙ", "support": "ድጋፍ",
"logout": "ውጣ", "get_help": "በስልክ ወይም በቴሌግራም እገዛ ያግኙ",
"app_settings": "የመተግበሪያ ቅንብሮች", "logout": "ውጣ",
"legal_and_information": "ሕጋዊ እና መረጃ", "app_settings": "የመተግበሪያ ቅንብሮች",
"change_language": "ቋንቋ ቀይር", "legal_and_information": "ሕጋዊ እና መረጃ",
"terms_and_conditions": "ውሎች እና ሁኔታዎች", "change_language": "ቋንቋ ቀይር",
"delete_account": "መለያ ሰርዝ", "terms_and_conditions": "ውሎች እና ሁኔታዎች",
"language_preference": "የቋንቋ ምርጫ", "delete_account": "መለያ ሰርዝ",
"choose_your_language": "ለውጦችን አስቀምጥ", "language_preference": "የቋንቋ ምርጫ",
"switch_language_anytime": "ቋንቋዎችን በማንኛውም ጊዜ መቀየር ይችላሉ", "choose_your_language": "ለውጦችን አስቀምጥ",
"need_help": "እገዛ ይፈልጋሉ?", "switch_language_anytime": "ቋንቋዎችን በማንኛውም ጊዜ መቀየር ይችላሉ",
"call_support": "የስልክ ድጋፍ", "need_help": "እገዛ ይፈልጋሉ?",
"talk_with_support": "በቀጥታ ከድጋፍ ቡድናችን ጋር ይነጋገሩ", "call_support": "የስልክ ድጋፍ",
"telegram_support": "የቴሌግራም ድጋፍ", "talk_with_support": "በቀጥታ ከድጋፍ ቡድናችን ጋር ይነጋገሩ",
"chat_via_telegram": "በቴሌግራም በፍጥነት ይወያዩ", "telegram_support": "የቴሌግራም ድጋፍ",
"call_our_support": "ከ3 ጠዋት እስከ 12 ማታ ድረስ የድጋፍ ቡድናችንን ይደውሉ", "chat_via_telegram": "በቴሌግራም በፍጥነት ይወያዩ",
"tap_to_call": "ለመደወል ይንኩ", "call_our_support": "ከ3 ጠዋት እስከ 12 ማታ ድረስ የድጋፍ ቡድናችንን ይደውሉ",
"join_telegram": "በቴሌግራም የይማሩ አካዳሚን ይቀላቀሉ", "tap_to_call": "ለመደወል ይንኩ",
"connect_with_support_team": "ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።", "join_telegram": "በቴሌግራም የይማሩ አካዳሚን ይቀላቀሉ",
"open_in_telegram": "በቴሌግራም ይክፈቱ", "connect_with_support_team":
"search_for": "ፈልጉት", "ለፈጣን እርዳታ እና የማህበረሰብ ዝማኔዎች፣ በቴሌግራም ከድጋፍ ቡድናችን ጋር ወዲያውኑ ይገናኙ።",
"current_level": "የአሁኑ ደረጃ", "open_in_telegram": "በቴሌግራም ይክፈቱ",
"keep_up_the_great_work": "በጣም ጥሩ እየሰራህ ነው! ቀጥልበት፣ አስደናቂ ነህ።", "search_for": "ፈልጉት",
"no_practice_available": "ምንም ልምምድ አልተገኘም!", "current_level": "የአሁኑ ደረጃ",
"begin_module_practice": "የሞጁሉን ልምምድ ጀምር", "keep_up_the_great_work": "በጣም ጥሩ እየሰራህ ነው! ቀጥልበት፣ አስደናቂ ነህ።",
"lets_practice_lesson": "እንለማመድ", "no_practice_available": "ምንም ልምምድ አልተገኘም!",
"lets_quickly_review": "በዚህ ሞጁል ውስጥ የተማርከውን በፍጥነት እንከልስ!", "begin_module_practice": "የሞጁሉን ልምምድ ጀምር",
"lets_practice_module": "አሁን የተማርከውን እንለማመድ!", "lets_practice_lesson": "እንለማመድ",
"ask_you_few_actions": "ጥቂት ጥያቄዎችን እጠይቅሃለሁ፣ አንተም በተፈጥሮ መልስ ልትሰጥ ትችላለህ።", "lets_quickly_review": "በዚህ ሞጁል ውስጥ የተማርከውን በፍጥነት እንከልስ!",
"begin_level_practice": "የደረጃ ልምምድን ጀምር", "lets_practice_module": "አሁን የተማርከውን እንለማመድ!",
"lets_practice_course": "የኮርሱን ልምምድ እንለማመድ", "ask_you_few_actions": "ጥቂት ጥያቄዎችን እጠይቅሃለሁ፣ አንተም በተፈጥሮ መልስ ልትሰጥ ትችላለህ።",
"lets_quick_review": "በዚህ ደረጃ የተማርከውን በፍጥነት እንከልስ!", "begin_level_practice": "የደረጃ ልምምድን ጀምር",
"speaking": "እየተናገረ ነው", "lets_practice_course": "የኮርሱን ልምምድ እንለማመድ",
"you_have_finished_practice": "ልምምድህን አጠናቀቅህ", "lets_quick_review": "በዚህ ደረጃ የተማርከውን በፍጥነት እንከልስ!",
"view_results": "ውጤቶቼን እይ", "speaking": "እየተናገረ ነው",
"sample_answer": "ናሙና መልስ", "you_have_finished_practice": "ልምምድህን አጠናቀቅህ",
"your_answer": "መልስህ", "view_results": "ውጤቶቼን እይ",
"sound_confident": "በዚህ ጊዜ የበለጠ እምነት ያለህ ይመስላል — በጣም ጥሩ መሻሻል ነው!", "sample_answer": "ናሙና መልስ",
"you_have_completed": "አያይ! አጠናቀቅህ", "your_answer": "መልስህ",
"yes": "አዎ", "sound_confident": "በዚህ ጊዜ የበለጠ እምነት ያለህ ይመስላል — በጣም ጥሩ መሻሻል ነው!",
"no": "አይ", "you_have_completed": "አያይ! አጠናቀቅህ",
"want_to_quit": "ለመውጣት እርግጠኛ ነህ?", "yes": "አዎ",
"required_field": "ይህ መስክ ያስፈልጋል", "no": "አይ",
"enter_full_name": "ሙሉ ስምህን አስገባ", "want_to_quit": "ለመውጣት እርግጠኛ ነህ?",
"invalid_email": "የማይሰራ የኢሜይል ቅርጸት", "required_field": "ይህ መስክ ያስፈልጋል",
"phone_must_start_with": "የስልክ ቁጥር በ251 መጀመር አለበት", "enter_full_name": "ሙሉ ስምህን አስገባ",
"phone_must_be": "የስልክ ቁጥር 12 አሃዞች መሆን አለበት", "invalid_email": "የማይሰራ የኢሜይል ቅርጸት",
"what_should_we_call_you": "ምን ብለን እንጠራህ?", "phone_must_start_with": "የስልክ ቁጥር በ251 መጀመር አለበት",
"name_for_personalization": "በመማር ጉዞህ ውስጥ ለግል ለማድረግ ስምህን እንጠቀማለን።", "phone_must_be": "የስልክ ቁጥር 12 አሃዞች መሆን አለበት",
"choose_your_gender": "ጾታህን ምረጥ", "what_should_we_call_you": "ምን ብለን እንጠራህ?",
"gender_for_personalization": "በጾታህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", "name_for_personalization": "በመማር ጉዞህ ውስጥ ለግል ለማድረግ ስምህን እንጠቀማለን።",
"age_range": "በየትኛው የእድሜ ክልል ውስጥ ነህ?", "choose_your_gender": "ጾታህን ምረጥ",
"age_for_personalization": "በእድሜህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", "gender_for_personalization": "በጾታህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።",
"educational_background": "አሁን ያለህ የትምህርት ደረጃ ምንድን ነው?", "age_range": "በየትኛው የእድሜ ክልል ውስጥ ነህ?",
"education_for_personalization": "ይህ ትምህርቶችን ከልምድህ ጋር እንዲስማሙ ለማድረግ ይረዳናል።", "age_for_personalization": "በእድሜህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።",
"your_occupation": "ስራህ ምንድን ነው?", "educational_background": "አሁን ያለህ የትምህርት ደረጃ ምንድን ነው?",
"occupation_for_personalization": "በስራህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።", "education_for_personalization": "ይህ ትምህርቶችን ከልምድህ ጋር እንዲስማሙ ለማድረግ ይረዳናል።",
"location": "ከየት ነህ?", "your_occupation": "ስራህ ምንድን ነው?",
"select_country_region": "አገርህን እና ክልልህን ከተቆልቋይ ዝርዝሩ ምረጥ", "occupation_for_personalization": "በስራህ መሰረት የመማር ተሞክሮህን እናበጅለታለን።",
"select_country": "አገር ምረጥ", "location": "ከየት ነህ?",
"learning_goal": "የመማር ዓላማህን ምረጥ", "select_country_region": "አገርህን እና ክልልህን ከተቆልቋይ ዝርዝሩ ምረጥ",
"language_goal": "እንግሊዝኛህን ለማሻሻል ዋና ዓላማህ ምንድን ነው?", "select_country": "አገር ምረጥ",
"your_goal": "ዓላማህ የመማር ጉዞህን እንዲስማማ ለማድረግ ይረዳናል።", "learning_goal": "የመማር ዓላማህን ምረጥ",
"write_your_goal": "ዓላማህን ጻፍ…", "language_goal": "እንግሊዝኛህን ለማሻሻል ዋና ዓላማህ ምንድን ነው?",
"challenge_you_face": "What challenge do you face most with English?", "your_goal": "ዓላማህ የመማር ጉዞህን እንዲስማማ ለማድረግ ይረዳናል።",
"evey_one_has_strugle": "ሁሉም ሰው ችግሮች አሉት፣ የአንተን እንጀምር እንፍታ", "write_your_goal": "ዓላማህን ጻፍ…",
"write_your_challenge": "ችግርህን ጻፍ…", "challenge_you_face": "What challenge do you face most with English?",
"topic_interest": "በጣም የሚስቡህ ርዕሶች የትኞቹ ናቸው?", "evey_one_has_strugle": "ሁሉም ሰው ችግሮች አሉት፣ የአንተን እንጀምር እንፍታ",
"favourite_topic": "የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።", "write_your_challenge": "ችግርህን ጻፍ…",
"your_interest": "ፍላጎትህን ጻፍ…", "topic_interest": "በጣም የሚስቡህ ርዕሶች የትኞቹ ናቸው?",
"want_quick_assessment": "የእንግሊዝኛ ደረጃህን ለማወቅ ፈጣን ግምገማ ትፈልጋለህ?", "favourite_topic":
"answer_quick_questions": "የእንግሊዝኛ ችሎታህን ለመረዳት ጥቂት ፈጣን ጥያቄዎችን መልስ።", "የምትወዳቸው ርዕሶች አስደሳች እና ከሕይወትህ ጋር የተዛመዱ ትምህርቶችን ለመፍጠር ይረዱናል።",
"skip": "ዝለል", "your_interest": "ፍላጎትህን ጻፍ…",
"finish_level": "ደረጃውን አጠናቅቅ", "want_quick_assessment": "የእንግሊዝኛ ደረጃህን ለማወቅ ፈጣን ግምገማ ትፈልጋለህ?",
"likely_speaker": "አንተ ምናልባት ተናጋሪ ነህ", "answer_quick_questions": "የእንግሊዝኛ ችሎታህን ለመረዳት ጥቂት ፈጣን ጥያቄዎችን መልስ።",
"great_job": "በጣም ጥሩ ስራ! ለመሻሻል ቀጣዩ ደረጃህ ይኸው ነው።", "skip": "ዝለል",
"lets_start_practice": "ልምምድህን እንጀምር", "finish_level": "ደረጃውን አጠናቅቅ",
"welcome_abroad": "እንኳን ደህና መጣህ", "likely_speaker": "አንተ ምናልባት ተናጋሪ ነህ",
"ready_to_explore": "የግል ትምህርቶችህን ለማሰስ ዝግጁ ነህ።", "great_job": "በጣም ጥሩ ስራ! ለመሻሻል ቀጣዩ ደረጃህ ይኸው ነው።",
"finish": "አጠናቅቅ", "lets_start_practice": "ልምምድህን እንጀምር",
"finish_all_practice_lesson": "ይህን ልምምድ ለመውሰድ የቀድሞውን የትምህርት ልምምድ ያጠናቅቁ", "welcome_abroad": "እንኳን ደህና መጣህ",
"finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ", "ready_to_explore": "የግል ትምህርቶችህን ለማሰስ ዝግጁ ነህ።",
"finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ", "finish": "አጠናቅቅ",
"finish_all_practice_previouse_module": "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ", "finish_all_practice_lesson": "ይህን ልምምድ ለመውሰድ የቀድሞውን የትምህርት ልምምድ ያጠናቅቁ",
"finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ", "finish_all_practice_module": "የሞጁሉን ልምምድ ለመውሰድ የትምህርት ልምምዶችን ያጠናቅቁ",
"track_journey": "የትምህርት ጉዞዎን ይከታተሉ እና በጊዜ ሂደት ያሳዩትን እድገት ይመልከቱ።", "finish_all_practice_course": "የኮርሱን ልምምድ ለመውሰድ የሞጁል ልምምዶችን ያጠናቅቁ",
"learn_english": "እንግሊዝኛ ይማሩ", "finish_all_practice_previouse_module":
"keep_momentum": "በጣም ጥሩ ስራ! በዚሁ ብርታት ይቀጥሉ።", "ይህን ልምምድ ለመውሰድ የቀድሞውን የሞጁል ልምምድ ያጠናቅቁ",
"completed_practices": "የተጠናቀቁ ልምምዶች", "finish_all_practice_previouse_course": "ይህን ለመውሰድ የቀድሞውን የኮርስ ልምምድ ያጠናቅቁ",
"total_practices": "ጠቅላላ ልምምዶች", "track_journey": "የትምህርት ጉዞዎን ይከታተሉ እና በጊዜ ሂደት ያሳዩትን እድገት ይመልከቱ።",
"progress_percentage": "የእድገት መቶኛ" "learn_english": "እንግሊዝኛ ይማሩ",
}; "keep_momentum": "በጣም ጥሩ ስራ! በዚሁ ብርታት ይቀጥሉ።",
static const Map<String,dynamic> _en = { "completed_practices": "የተጠናቀቁ ልምምዶች",
"loading": "Loading", "total_practices": "ጠቅላላ ልምምዶች",
"welcome_back": "Welcome back", "progress_percentage": "የእድገት መቶኛ"
"checking_user_info": "Checking user info", };
"dont_have_account": "Don't have an account?", static const Map<String, dynamic> _en = {
"email": "Email", "loading": "Loading",
"password": "Password", "welcome_back": "Welcome back",
"forgot_password": "Forgot password?", "checking_user_info": "Checking user info",
"cont": "Continue", "dont_have_account": "Don't have an account?",
"register": "Register", "email": "Email",
"login_with_google": "Login with Google", "password": "Password",
"or": "Or", "forgot_password": "Forgot password?",
"login_with_phone": "Login with phone number", "cont": "Continue",
"create_account": "Create an account", "register": "Register",
"already_have_account": "Already have an account?", "login_with_google": "Login with Google",
"login": "Login", "or": "Or",
"register_with_google": "Register with Google", "login_with_phone": "Login with phone number",
"register_with_phone": "Register with phone number", "create_account": "Create an account",
"enter_phone_number": "Enter your phone number. We will send you a confirmation code there.", "already_have_account": "Already have an account?",
"login_with_email": "Login with email", "login": "Login",
"create_password": "Create password", "register_with_google": "Register with Google",
"confirm_password": "Confirm password", "register_with_phone": "Register with phone number",
"eight_character_minimum": "8 characters minimum", "enter_phone_number":
"password_match": "password match", "Enter your phone number. We will send you a confirmation code there.",
"sign_up_agreement": "By clicking Sign Up, you agree to our Terms of Service and Privacy Policy", "login_with_email": "Login with email",
"terms_of_services": "Terms of Service", "create_password": "Create password",
"and": "and", "confirm_password": "Confirm password",
"privacy_policy": "Privacy Policy", "eight_character_minimum": "8 characters minimum",
"register_with_email": "Register with email", "password_match": "password match",
"verification_code": "Verification Code", "sign_up_agreement":
"resend_code": "Resend Code", "By clicking Sign Up, you agree to our Terms of Service and Privacy Policy",
"code_sent_to_phone": "Code sent to your number", "terms_of_services": "Terms of Service",
"code_sent_to_email": "Code sent to your email", "and": "and",
"resend_code_in": "Resend code in", "privacy_policy": "Privacy Policy",
"reset_password": "Reset Password", "register_with_email": "Register with email",
"enter_email_reset_code": "Enter your email. We will send you a reset code.", "verification_code": "Verification Code",
"please_wait": "Please wait", "resend_code": "Resend Code",
"reset_code_sent": "Reset code sent successfully", "code_sent_to_phone": "Code sent to your number",
"reset_code": "Reset code", "code_sent_to_email": "Code sent to your email",
"new_password": "New password", "resend_code_in": "Resend code in",
"logged_in_successfully": "Logged in successfully", "reset_password": "Reset Password",
"continue_learning": "Continue Learning", "enter_email_reset_code":
"start_learning": "Start Learning", "Enter your email. We will send you a reset code.",
"completed": "Completed", "please_wait": "Please wait",
"view_course": "View course", "reset_code_sent": "Reset code sent successfully",
"take_practice": "Take practice", "reset_code": "Reset code",
"your_current_level": "Your current level", "new_password": "New password",
"overall_progress": "Overall progress", "logged_in_successfully": "Logged in successfully",
"great_work": "Keep up the great work! You're doing amazing", "continue_learning": "Continue Learning",
"view_module": "View module", "start_learning": "Start Learning",
"progress": "Progress", "completed": "Completed",
"keep_going": "Let's keep going - you're more than half there", "view_course": "View course",
"lessons_in_module": "Lessons in this module", "take_practice": "Take practice",
"practice": "Practice", "your_current_level": "Your current level",
"start": "Start", "overall_progress": "Overall progress",
"in_progress": "In Progress", "great_work": "Keep up the great work! You're doing amazing",
"hello": "Hello", "view_module": "View module",
"ready_to_learn": "Ready to keep learning English today", "progress": "Progress",
"learn": "Learn", "keep_going": "Let's keep going - you're more than half there",
"course": "Course", "lessons_in_module": "Lessons in this module",
"profile": "Profile", "practice": "Practice",
"speaking_partner": "Speaking partner", "start": "Start",
"practice_what_you_learned": "Let's practice what you just learnt", "in_progress": "In Progress",
"practice_questions": "I will ask you a few questions and you can respond", "hello": "Hello",
"start_practice": "Start practice", "ready_to_learn": "Ready to keep learning English today",
"almost_there": "You're almost there", "learn": "Learn",
"finish_session": "Finish the session to see your progress", "course": "Course",
"continue_practice": "Continue practice", "profile": "Profile",
"end_session": "End session", "speaking_partner": "Speaking partner",
"tap_start_to_listen": "Tap the start button to listen", "practice_what_you_learned": "Let's practice what you just learnt",
"practice_speaking": "Practice speaking", "practice_questions": "I will ask you a few questions and you can respond",
"tap_microphone": "Tap the microphone to speak", "start_practice": "Start practice",
"reply": "Reply", "almost_there": "You're almost there",
"cancel": "Cancel", "finish_session": "Finish the session to see your progress",
"you_are_speaking": "You're speaking", "continue_practice": "Continue practice",
"practice_completed": "Practice completed!", "end_session": "End session",
"great_improvement": "You sound more confident this time, great improvement", "tap_start_to_listen": "Tap the start button to listen",
"practice_again": "Practice again", "practice_speaking": "Practice speaking",
"conversation_review": "Conversation review", "tap_microphone": "Tap the microphone to speak",
"result": "Result", "reply": "Reply",
"quick_tip": "Quick tip", "cancel": "Cancel",
"retry": "Retry", "you_are_speaking": "You're speaking",
"completed_a1": "Yay, you've completed A1", "practice_completed": "Practice completed!",
"analyzing_speaking": "We're now analyzing your speaking skill", "great_improvement":
"view_profile": "View profile", "You sound more confident this time, great improvement",
"hi": "Hi", "practice_again": "Practice again",
"edit_profile": "Edit profile", "conversation_review": "Conversation review",
"first_name": "First name", "result": "Result",
"last_name": "Last name", "quick_tip": "Quick tip",
"gender": "Gender", "retry": "Retry",
"male": "Male", "completed_a1": "Yay, you've completed A1",
"female": "Female", "analyzing_speaking": "We're now analyzing your speaking skill",
"phone_number": "Phone number", "view_profile": "View profile",
"country": "Country", "hi": "Hi",
"region": "Region", "edit_profile": "Edit profile",
"select_region": "Select region", "first_name": "First name",
"enter_your_city": "Enter your city", "last_name": "Last name",
"occupation": "Occupation", "gender": "Gender",
"select_occupation": "Select occupation", "male": "Male",
"save_changes": "Save changes", "female": "Female",
"my_progress": "My progress", "phone_number": "Phone number",
"track_your_achievement": "Track your achievements and learning streak", "country": "Country",
"account_and_privacy": "Account & Privacy", "region": "Region",
"manage_settings": "Manage settings and app preference", "select_region": "Select region",
"support": "Support", "enter_your_city": "Enter your city",
"get_help": "Get help through phone or Telegram", "occupation": "Occupation",
"logout": "Logout", "select_occupation": "Select occupation",
"app_settings": "App settings", "save_changes": "Save changes",
"legal_and_information": "Legal & Information", "my_progress": "My progress",
"change_language": "Change language", "track_your_achievement": "Track your achievements and learning streak",
"terms_and_conditions": "Terms & Conditions", "account_and_privacy": "Account & Privacy",
"delete_account": "Delete account", "manage_settings": "Manage settings and app preference",
"language_preference": "Language preference", "support": "Support",
"choose_your_language": "Choose your language", "get_help": "Get help through phone or Telegram",
"switch_language_anytime": "You can switch languages anytime", "logout": "Logout",
"need_help": "Need help?", "app_settings": "App settings",
"call_support": "Call support", "legal_and_information": "Legal & Information",
"talk_with_support": "Talk with our support team directly", "change_language": "Change language",
"telegram_support": "Telegram support", "terms_and_conditions": "Terms & Conditions",
"chat_via_telegram": "Chat instantly via Telegram", "delete_account": "Delete account",
"call_our_support": "Call our support team between 9 AM - 6 PM", "language_preference": "Language preference",
"tap_to_call": "Tap to call", "choose_your_language": "Choose your language",
"join_telegram": "Join Yimaru Academy on Telegram", "switch_language_anytime": "You can switch languages anytime",
"connect_with_support_team": "Connect with our support team instantly on Telegram for quick assistance and community updates", "need_help": "Need help?",
"open_in_telegram": "Open in Telegram", "call_support": "Call support",
"search_for": "Search for", "talk_with_support": "Talk with our support team directly",
"current_level": "Current Level", "telegram_support": "Telegram support",
"keep_up_the_great_work": "Keep up the great work! You're doing amazing.", "chat_via_telegram": "Chat instantly via Telegram",
"no_practice_available": "No practice available!", "call_our_support": "Call our support team between 9 AM - 6 PM",
"begin_module_practice": "Begin Module Practice", "tap_to_call": "Tap to call",
"lets_practice_lesson": "Lets Practice", "join_telegram": "Join Yimaru Academy on Telegram",
"lets_quickly_review": "Lets quickly review what youve learned in this module!", "connect_with_support_team":
"lets_practice_module": "Let's practice what you just learnt!", "Connect with our support team instantly on Telegram for quick assistance and community updates",
"ask_you_few_actions": "Ill ask you a few questions, and you can respond naturally.", "open_in_telegram": "Open in Telegram",
"begin_level_practice": "Begin Level Practice", "search_for": "Search for",
"lets_practice_course": "Lets Practice Course", "current_level": "Current Level",
"lets_quick_review": "Lets quickly review what youve learned in this level!", "keep_up_the_great_work": "Keep up the great work! You're doing amazing.",
"speaking": "is speaking...", "no_practice_available": "No practice available!",
"you_have_finished_practice": "You have finished your practice", "begin_module_practice": "Begin Module Practice",
"view_results": "View My Results", "lets_practice_lesson": "Lets Practice",
"sample_answer": "Sample Answer", "lets_quickly_review":
"your_answer": "Your Answer", "Lets quickly review what youve learned in this module!",
"sound_confident": "You sound more confident this time - great improvement!", "lets_practice_module": "Let's practice what you just learnt!",
"you_have_completed": "Yay, youve completed", "ask_you_few_actions":
"yes": "Yes", "Ill ask you a few questions, and you can respond naturally.",
"no": "No", "begin_level_practice": "Begin Level Practice",
"want_to_quit": "Are you sure you want to quit?", "lets_practice_course": "Lets Practice Course",
"required_field": "The field is required", "lets_quick_review":
"enter_full_name": "Enter your full name", "Lets quickly review what youve learned in this level!",
"invalid_email": "Invalid email format", "speaking": "is speaking...",
"phone_must_start_with": "Phone number must start with 251", "you_have_finished_practice": "You have finished your practice",
"phone_must_be": "Phone number must be 12 digits", "view_results": "View My Results",
"what_should_we_call_you": "What should we call you?", "sample_answer": "Sample Answer",
"name_for_personalization": "Well use your name to personalize your learning journey.", "your_answer": "Your Answer",
"choose_your_gender": "Choose your gender?", "sound_confident":
"gender_for_personalization": "Well personalize your learning experience based on your gender.", "You sound more confident this time - great improvement!",
"age_range": "Which age range are you in?", "you_have_completed": "Yay, youve completed",
"age_for_personalization": "Well personalize your learning experience based on your age.", "yes": "Yes",
"educational_background": "Whats your current educational level?", "no": "No",
"education_for_personalization": "This helps us tailor your lessons to your experience.", "want_to_quit": "Are you sure you want to quit?",
"your_occupation": "Whats your occupation?", "required_field": "The field is required",
"occupation_for_personalization": "Well personalize your learning experience based on your occupation.", "enter_full_name": "Enter your full name",
"location": "Where are you from?", "invalid_email": "Invalid email format",
"select_country_region": "Select your country and region from the dropdown", "phone_must_start_with": "Phone number must start with 251",
"select_country": "Select country", "phone_must_be": "Phone number must be 12 digits",
"learning_goal": "Choose your learning goal.", "what_should_we_call_you": "What should we call you?",
"language_goal": "Whats your main goal for improving your English?", "name_for_personalization":
"your_goal": "Your goal helps us tailor your learning journey.", "Well use your name to personalize your learning journey.",
"write_your_goal": "Write your goal…", "choose_your_gender": "Choose your gender?",
"challenge_you_face": "What challenge do you face most with English?", "gender_for_personalization":
"evey_one_has_strugle": "Everyone has struggles, lets start fixing yours", "Well personalize your learning experience based on your gender.",
"write_your_challenge": "Write your challenge…", "age_range": "Which age range are you in?",
"topic_interest": "Which topics interest you most?", "age_for_personalization":
"favourite_topic": "Your favorite topics help us create fun, relatable lessons.", "Well personalize your learning experience based on your age.",
"your_interest": "Write your interest…", "educational_background": "Whats your current educational level?",
"want_quick_assessment": "Want a quick assessment to know your English level?", "education_for_personalization":
"answer_quick_questions": "Answer a few quick questions to help us understand your English proficiency.", "This helps us tailor your lessons to your experience.",
"skip": "Skip", "your_occupation": "Whats your occupation?",
"finish_level": "Finish Level", "occupation_for_personalization":
"likely_speaker": "Youre likely speaker of", "Well personalize your learning experience based on your occupation.",
"great_job": "Great Job! Heres your next step to keep improving.", "location": "Where are you from?",
"lets_start_practice": "Let's start your practice", "select_country_region": "Select your country and region from the dropdown",
"welcome_abroad": "Welcome aboard", "select_country": "Select country",
"ready_to_explore": "Youre ready to explore your personalized lessons.", "learning_goal": "Choose your learning goal.",
"finish": "Finish", "language_goal": "Whats your main goal for improving your English?",
"finish_all_practice_lesson": "Finish the previous lesson practice to take this practice", "your_goal": "Your goal helps us tailor your learning journey.",
"finish_all_practice_module": "Finish the lesson practices to take the Module Practice", "write_your_goal": "Write your goal…",
"finish_all_practice_course": "Finish the Module practices to take the Course practice", "challenge_you_face": "What challenge do you face most with English?",
"finish_all_practice_previouse_module": "Finish the previous Module practice to take this practice", "evey_one_has_strugle": "Everyone has struggles, lets start fixing yours",
"finish_all_practice_previouse_course": "Finish the previous course practice to take this", "write_your_challenge": "Write your challenge…",
"track_journey": "Track your learning journey and see your growth over time.", "topic_interest": "Which topics interest you most?",
"learn_english": "Learn English", "favourite_topic":
"keep_momentum": "Great job! Keep the momentum.", "Your favorite topics help us create fun, relatable lessons.",
"completed_practices": "Completed Practices", "your_interest": "Write your interest…",
"total_practices": "Total Practices", "want_quick_assessment":
"progress_percentage": "Progress Percentage" "Want a quick assessment to know your English level?",
}; "answer_quick_questions":
static const Map<String, Map<String,dynamic>> mapLocales = {"am": _am, "en": _en}; "Answer a few quick questions to help us understand your English proficiency.",
"skip": "Skip",
"finish_level": "Finish Level",
"likely_speaker": "Youre likely speaker of",
"great_job": "Great Job! Heres your next step to keep improving.",
"lets_start_practice": "Let's start your practice",
"welcome_abroad": "Welcome aboard",
"ready_to_explore": "Youre 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.",
"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
};
} }

View File

@ -2,7 +2,7 @@
// ignore_for_file: constant_identifier_names // ignore_for_file: constant_identifier_names
abstract class LocaleKeys { abstract class LocaleKeys {
static const loading = 'loading'; static const loading = 'loading';
static const welcome_back = 'welcome_back'; static const welcome_back = 'welcome_back';
static const checking_user_info = 'checking_user_info'; static const checking_user_info = 'checking_user_info';
@ -161,7 +161,8 @@ abstract class LocaleKeys {
static const educational_background = 'educational_background'; static const educational_background = 'educational_background';
static const education_for_personalization = 'education_for_personalization'; static const education_for_personalization = 'education_for_personalization';
static const your_occupation = 'your_occupation'; 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 location = 'location';
static const select_country_region = 'select_country_region'; static const select_country_region = 'select_country_region';
static const select_country = 'select_country'; 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_lesson = 'finish_all_practice_lesson';
static const finish_all_practice_module = 'finish_all_practice_module'; 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_course = 'finish_all_practice_course';
static const finish_all_practice_previouse_module = 'finish_all_practice_previouse_module'; static const finish_all_practice_previouse_module =
static const finish_all_practice_previouse_course = 'finish_all_practice_previouse_course'; '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 track_journey = 'track_journey';
static const learn_english = 'learn_english'; static const learn_english = 'learn_english';
static const keep_momentum = 'keep_momentum'; static const keep_momentum = 'keep_momentum';
static const completed_practices = 'completed_practices'; static const completed_practices = 'completed_practices';
static const total_practices = 'total_practices'; static const total_practices = 'total_practices';
static const progress_percentage = 'progress_percentage'; static const progress_percentage = 'progress_percentage';
} }

View File

@ -55,8 +55,6 @@ class HomeViewModel extends ReactiveViewModel {
rebuildUi(); rebuildUi();
} }
// Remote api calls // Remote api calls
// In-app update // In-app update

View File

@ -28,14 +28,13 @@ class LanguageViewModel extends ReactiveViewModel {
_localizationService.isSelectedLanguage(title); _localizationService.isSelectedLanguage(title);
Future<void> setSelectedLanguage( Future<void> setSelectedLanguage(
{required BuildContext context, {required BuildContext context,
required Map<String, dynamic> title}) async { required Map<String, dynamic> title}) async {
await _localizationService.setSelectedLanguage( await _localizationService.setSelectedLanguage(
context: context, title: title); context: context, title: title);
rebuildUi(); rebuildUi();
} }
// Navigation // Navigation
void pop() => _navigationService.back(); void pop() => _navigationService.back();
} }

View File

@ -13,8 +13,10 @@ import 'learn_course_viewmodel.dart';
class LearnCourseView extends StackedView<LearnCourseViewModel> { class LearnCourseView extends StackedView<LearnCourseViewModel> {
final int id; 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( Future<void> _onPractice(
{required BuildContext context, {required BuildContext context,
@ -151,7 +153,9 @@ class LearnCourseView extends StackedView<LearnCourseViewModel> {
viewModel: viewModel, viewModel: viewModel,
course: viewModel.courses[index]), course: viewModel.courses[index]),
onViewTap: () async => onViewTap: () async =>
await viewModel.navigateToLearnModule(viewModel.courses[index]), await viewModel.navigateToLearnModule(
first: first && index ==0,
course: viewModel.courses[index]),
), ),
separatorBuilder: (context, index) => verticalSpaceSmall, separatorBuilder: (context, index) => verticalSpaceSmall,
); );

View File

@ -32,8 +32,8 @@ class LearnCourseViewModel extends ReactiveViewModel {
Future<void> navigateToLearnSubscription() async => Future<void> navigateToLearnSubscription() async =>
await _navigationService.navigateToLearnSubscriptionView(); await _navigationService.navigateToLearnSubscriptionView();
Future<void> navigateToLearnModule(LearnCourse course) async => Future<void> navigateToLearnModule({required bool first,required LearnCourse course}) async =>
_navigationService.navigateToLearnModuleView(course: course); _navigationService.navigateToLearnModuleView(first: first,course: course);
Future<void> navigateToLearnPractice( Future<void> navigateToLearnPractice(
{required int id, required String level}) async => {required int id, required String level}) async =>

View File

@ -17,32 +17,25 @@ import '../../widgets/small_app_bar.dart';
import 'learn_lesson_viewmodel.dart'; import 'learn_lesson_viewmodel.dart';
class LearnLessonView extends StackedView<LearnLessonViewModel> { class LearnLessonView extends StackedView<LearnLessonViewModel> {
final bool first;
final LearnModule module; 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( Future<void> _onPractice(
{required int index, {required int index,
required LearnLesson lesson, required LearnLesson lesson,
required BuildContext context, required BuildContext context,
required LearnLessonViewModel viewModel}) async { required LearnLessonViewModel viewModel}) async {
/* if (lesson.access?.isAccessible ?? false) { if (viewModel.user?.subscriptionStatus?.toLowerCase() == 'active') {
await viewModel.navigateToLearnPractice(lesson.id ?? 0); if (lesson.access?.isAccessible ?? false) {
} else { await viewModel.navigateToLearnPractice(lesson.id ?? 0);
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);
} else {
await _showSheet(context: context, viewModel: viewModel);
}
} else { } else {
await viewModel.navigateToLearnSubscription(); await _showSheet(context: context, viewModel: viewModel);
} }
} else { } else {
if (lesson.access?.isAccessible ?? false) { if (first && index < 3) {
await viewModel.navigateToLearnPractice(lesson.id ?? 0); await viewModel.navigateToLearnPractice(lesson.id ?? 0);
} else { } else {
await _showSheet(context: context, viewModel: viewModel); await _showSheet(context: context, viewModel: viewModel);
@ -224,6 +217,7 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => _buildTile( itemBuilder: (context, index) => _buildTile(
index: index, index: index,
first: first && index < 3,
lesson: viewModel.lessons[index], lesson: viewModel.lessons[index],
last: index == viewModel.lessons.length - 1, last: index == viewModel.lessons.length - 1,
onPracticeTap: () async => await _onPractice( onPracticeTap: () async => await _onPractice(
@ -244,12 +238,14 @@ class LearnLessonView extends StackedView<LearnLessonViewModel> {
Widget _buildTile({ Widget _buildTile({
required bool last, required bool last,
required int index, required int index,
required bool first,
required LearnLesson lesson, required LearnLesson lesson,
required GestureTapCallback? onLessonTap, required GestureTapCallback? onLessonTap,
required GestureTapCallback? onPracticeTap, required GestureTapCallback? onPracticeTap,
}) => }) =>
LearnLessonTile( LearnLessonTile(
last: last, last: last,
first: first,
index: index, index: index,
lesson: lesson, lesson: lesson,
onLessonTap: onLessonTap, onLessonTap: onLessonTap,

View File

@ -31,21 +31,9 @@ class LearnLessonDetailView extends StackedView<LearnLessonDetailViewModel> {
Future<void> _onPractice( Future<void> _onPractice(
{required LearnLesson lesson, {required LearnLesson lesson,
required LearnLessonDetailViewModel viewModel}) async { required LearnLessonDetailViewModel viewModel}) async {
/* await viewModel.pause(); await viewModel.pause();
await viewModel.navigateToLearnPractice(lesson.id ?? 0); 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 @override

View File

@ -16,9 +16,11 @@ import '../../widgets/small_app_bar.dart';
import 'learn_module_viewmodel.dart'; import 'learn_module_viewmodel.dart';
class LearnModuleView extends StackedView<LearnModuleViewModel> { class LearnModuleView extends StackedView<LearnModuleViewModel> {
final bool first;
final LearnCourse course; 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( Future<void> _onPractice(
{required BuildContext context, {required BuildContext context,
@ -202,7 +204,9 @@ class LearnModuleView extends StackedView<LearnModuleViewModel> {
module: viewModel.modules[index], module: viewModel.modules[index],
), ),
onModuleTap: () async => onModuleTap: () async =>
await viewModel.navigateToLearnLesson(viewModel.modules[index]), await viewModel.navigateToLearnLesson(
first: first && index == 0,
module: viewModel.modules[index]),
), ),
); );

View File

@ -35,8 +35,8 @@ class LearnModuleViewModel extends ReactiveViewModel {
// Navigation // Navigation
void pop() => _navigationService.back(); void pop() => _navigationService.back();
Future<void> navigateToLearnLesson(LearnModule module) async => Future<void> navigateToLearnLesson({required bool first, required LearnModule module}) async =>
await _navigationService.navigateToLearnLessonView(module: module); await _navigationService.navigateToLearnLessonView(first:first,module: module);
Future<void> navigateToLearnPractice( Future<void> navigateToLearnPractice(
{required int id, required String module}) async => {required int id, required String module}) async =>

View File

@ -10,6 +10,7 @@ import 'package:yimaru_app/services/voice_recorder_service.dart';
import 'package:yimaru_app/ui/common/enmus.dart'; import 'package:yimaru_app/ui/common/enmus.dart';
import '../../../app/app.locator.dart'; import '../../../app/app.locator.dart';
import '../../../app/app.router.dart';
import '../../../models/learn_question.dart'; import '../../../models/learn_question.dart';
import '../../../services/api_service.dart'; import '../../../services/api_service.dart';
import '../../../services/audio_player_service.dart'; import '../../../services/audio_player_service.dart';
@ -264,6 +265,9 @@ class LearnPracticeViewModel extends ReactiveViewModel {
// Navigation // Navigation
void pop() => _navigationService.back(); void pop() => _navigationService.back();
Future<void> navigateToLearnSubscription() async =>
await _navigationService.navigateToLearnSubscriptionView();
// Remote api call // Remote api call
// Refresh url // Refresh url

View File

@ -27,6 +27,14 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
required this.subtitle, required this.subtitle,
required this.practice}); 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 { Future<void> _cancel(LearnPracticeViewModel viewModel) async {
await viewModel.stopRecording(); await viewModel.stopRecording();
viewModel.pop(); viewModel.pop();
@ -207,7 +215,7 @@ class LearnPracticeIntroScreen extends ViewModelWidget<LearnPracticeViewModel> {
text: label, text: label,
borderRadius: 12, borderRadius: 12,
foregroundColor: kcWhite, foregroundColor: kcWhite,
onTap: () => viewModel.goTo(1),
backgroundColor: kcPrimaryColor, backgroundColor: kcPrimaryColor,
onTap: () async => await _practice(viewModel),
); );
} }

View File

@ -87,8 +87,8 @@ class LearnProgramView extends StackedView<LearnProgramViewModel> {
separatorBuilder: (context, index) => verticalSpaceSmall, separatorBuilder: (context, index) => verticalSpaceSmall,
itemBuilder: (context, index) => _buildTile( itemBuilder: (context, index) => _buildTile(
program: viewModel.learnPrograms[index], program: viewModel.learnPrograms[index],
onTap: () async => await viewModel onTap: () async => await viewModel.navigateToLearnCourse(
.navigateToLearnCourse(viewModel.learnPrograms[index].id ?? 0), first: index == 0, id: viewModel.learnPrograms[index].id ?? 0),
), ),
); );

View File

@ -36,8 +36,8 @@ class LearnProgramViewModel extends ReactiveViewModel {
List<LearnProgram> get learnPrograms => _learnPrograms; List<LearnProgram> get learnPrograms => _learnPrograms;
// Navigation // Navigation
Future<void> navigateToLearnCourse(int id) async => Future<void> navigateToLearnCourse({required int id,required bool first}) async =>
_navigationService.navigateToLearnCourseView(id: id); _navigationService.navigateToLearnCourseView(id: id,first: first);
// Remote api call // Remote api call

View File

@ -205,8 +205,8 @@ class OnboardingViewModel extends ReactiveViewModel
_selectedCountry = value; _selectedCountry = value;
if (value?.code?.toLowerCase().trim() == 'et') { if (value?.code?.toLowerCase().trim() == 'et') {
_dropdownRegion = true; _dropdownRegion = true;
_selectedRegion = _regions _selectedRegion = _regions.firstWhere(
.firstWhere((e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false); (e) => e.code?.toLowerCase().trim().contains('addis_ababa') ?? false);
} else { } else {
_dropdownRegion = false; _dropdownRegion = false;
} }

View File

@ -26,7 +26,8 @@ class PaymentView extends StackedView<PaymentViewModel> {
@override @override
void onViewModelReady(PaymentViewModel viewModel) async { void onViewModelReady(PaymentViewModel viewModel) async {
await viewModel.createLearnSubscriptionRequest(phone: phone,subscription: subscription); await viewModel.createLearnSubscriptionRequest(
phone: phone, subscription: subscription);
super.onViewModelReady(viewModel); super.onViewModelReady(viewModel);
} }

View File

@ -45,18 +45,22 @@ class PaymentViewModel extends ReactiveViewModel {
// Remote api call // Remote api call
// Learn subscription // Learn subscription
Future<void> createLearnSubscriptionRequest({required String phone,required LearnSubscription subscription}) async => Future<void> createLearnSubscriptionRequest(
await runBusyFuture(_createLearnSubscriptionRequest(phone: phone,subscription: subscription), {required String phone,
required LearnSubscription subscription}) async =>
await runBusyFuture(
_createLearnSubscriptionRequest(
phone: phone, subscription: subscription),
busyObject: StateObjects.learnSubscription); 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()) { if (await _statusChecker.checkConnection()) {
Map<String, dynamic> data = { Map<String, dynamic> data = {
'provider': 'CHAPA', 'provider': 'CHAPA',
'phone': '251$phone', 'phone': '251$phone',
'email': 'test@gmail.com', 'email': 'test@gmail.com',
'plan_id': subscription.id, 'plan_id': subscription.id,
}; };
Map<String, dynamic> response = Map<String, dynamic> response =

View File

@ -166,7 +166,7 @@ class ProfileView extends StackedView<ProfileViewModel> {
List<Widget> _buildSettingsChildren(ProfileViewModel viewModel) => [ List<Widget> _buildSettingsChildren(ProfileViewModel viewModel) => [
// _buildDownloadsCard(viewModel), // _buildDownloadsCard(viewModel),
_buildProgressCard(viewModel), _buildProgressCard(viewModel),
_buildAccountCard(viewModel), _buildAccountCard(viewModel),
_buildSupportCard(viewModel) _buildSupportCard(viewModel)
]; ];

View File

@ -104,7 +104,7 @@ class ProfileDetailView extends StackedView<ProfileDetailViewModel>
viewModel.setSelectedOccupation(viewModel.occupations viewModel.setSelectedOccupation(viewModel.occupations
.where((e) => (e.code ?? '') == viewModel.user?.occupation) .where((e) => (e.code ?? '') == viewModel.user?.occupation)
.first); .first);
viewModel.setSelectedCountry(viewModel.countries viewModel.setSelectedCountry(viewModel.countries
.where((e) => (e.code ?? '') == viewModel.user?.country) .where((e) => (e.code ?? '') == viewModel.user?.country)
.first); .first);
if (viewModel.user?.country?.toLowerCase() == 'et') { if (viewModel.user?.country?.toLowerCase() == 'et') {

View File

@ -136,8 +136,8 @@ class ProfileDetailViewModel extends ReactiveViewModel
void setEthiopianRegion(String region) { void setEthiopianRegion(String region) {
_dropdownRegion = true; _dropdownRegion = true;
_selectedRegion = _selectedRegion = _regions
_regions.firstWhere((r) => r.code?.toLowerCase() == region.toLowerCase()); .firstWhere((r) => r.code?.toLowerCase() == region.toLowerCase());
rebuildUi(); rebuildUi();
} }

View File

@ -17,7 +17,6 @@ class ProgressViewModel extends ReactiveViewModel {
@override @override
List<ListenableServiceMixin> get listenableServices => [_learnService]; List<ListenableServiceMixin> get listenableServices => [_learnService];
// Total practice count // Total practice count
int get _totalCount => _learnService.totalCount; int get _totalCount => _learnService.totalCount;
@ -33,7 +32,6 @@ class ProgressViewModel extends ReactiveViewModel {
int get totalProgress => _totalProgress; int get totalProgress => _totalProgress;
// Courses // Courses
final List<Map<String, dynamic>> _courses = [ final List<Map<String, dynamic>> _courses = [
{ {
@ -53,8 +51,9 @@ class ProgressViewModel extends ReactiveViewModel {
// Learning progress // Learning progress
Future<void> getProgressSummary() async => runBusyFuture(_getProgressSummary(), Future<void> getProgressSummary() async =>
busyObject: StateObjects.progressSummary); runBusyFuture(_getProgressSummary(),
busyObject: StateObjects.progressSummary);
Future<void> _getProgressSummary() async { Future<void> _getProgressSummary() async {
if (await _statusCheckerService.checkConnection()) { if (await _statusCheckerService.checkConnection()) {

View File

@ -17,6 +17,7 @@ import 'custom_linear_progress_indicator.dart';
class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> { class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
final int index; final int index;
final bool last; final bool last;
final bool first;
final LearnLesson lesson; final LearnLesson lesson;
final GestureTapCallback? onLessonTap; final GestureTapCallback? onLessonTap;
final GestureTapCallback? onPracticeTap; final GestureTapCallback? onPracticeTap;
@ -26,6 +27,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
this.onLessonTap, this.onLessonTap,
this.onPracticeTap, this.onPracticeTap,
required this.last, required this.last,
required this.first,
required this.index, required this.index,
required this.lesson}); required this.lesson});
@ -35,7 +37,9 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
Widget _buildContainerWrapper(LearnLessonViewModel viewModel) => Widget _buildContainerWrapper(LearnLessonViewModel viewModel) =>
GestureDetector( 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), child: _buildContainer(viewModel),
); );
@ -56,7 +60,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
Widget _buildTileStack(LearnLessonViewModel viewModel) => Stack( Widget _buildTileStack(LearnLessonViewModel viewModel) => Stack(
children: [ children: [
_buildExpansionTile(viewModel), _buildExpansionTile(viewModel),
_buildContainerShaderState() _buildContainerShaderState(viewModel)
], ],
); );
@ -70,7 +74,6 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
shape: Border.all(color: kcTransparent), shape: Border.all(color: kcTransparent),
expandedAlignment: Alignment.centerLeft, expandedAlignment: Alignment.centerLeft,
leading: _buildLeadingWrapper(viewModel), leading: _buildLeadingWrapper(viewModel),
enabled: (lesson.access?.isAccessible ?? false),
controlAffinity: ListTileControlAffinity.trailing, controlAffinity: ListTileControlAffinity.trailing,
expandedCrossAxisAlignment: CrossAxisAlignment.start, expandedCrossAxisAlignment: CrossAxisAlignment.start,
tilePadding: const EdgeInsets.fromLTRB(15, 15, 15, 15), tilePadding: const EdgeInsets.fromLTRB(15, 15, 15, 15),
@ -85,6 +88,7 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
collapsedBackgroundColor: (lesson.access?.isCompleted ?? false) collapsedBackgroundColor: (lesson.access?.isCompleted ?? false)
? kcGreen.withOpacity(0.1) ? kcGreen.withOpacity(0.1)
: kcPrimaryColor.withOpacity(0.1), : kcPrimaryColor.withOpacity(0.1),
enabled: first ? true : (lesson.access?.isAccessible ?? false),
children: _buildExpansionTileChildren(viewModel), children: _buildExpansionTileChildren(viewModel),
); );
@ -203,9 +207,14 @@ class LearnLessonTile extends ViewModelWidget<LearnLessonViewModel> {
backgroundColor: kcPrimaryColor, backgroundColor: kcPrimaryColor,
); );
Widget _buildContainerShaderState() => !(lesson.access?.isAccessible ?? false) Widget _buildContainerShaderState(LearnLessonViewModel viewModel) =>
? _buildContainerShader() viewModel.user?.subscriptionStatus?.toLowerCase() == 'active'
: Container(); ? !(lesson.access?.isAccessible ?? false)
? _buildContainerShader()
: Container()
: !first
? _buildContainerShader()
: Container();
Widget _buildContainerShader() => const CustomContainerShader(); Widget _buildContainerShader() => const CustomContainerShader();
} }

View File

@ -1,6 +1,6 @@
name: yimaru_app name: yimaru_app
publish_to: 'none' publish_to: 'none'
version: 0.1.33+35 version: 0.1.34+36
description: A new Flutter project. description: A new Flutter project.
environment: environment: