diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 005d2b7..c5bc4f8 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,43 +1,79 @@ +import java.util.Properties +import java.io.FileInputStream + plugins { - id("kotlin-android") id("com.android.application") + id("org.jetbrains.kotlin.android") id("com.google.gms.google-services") id("dev.flutter.flutter-gradle-plugin") } +val keystoreProperties = Properties() +val keystorePropertiesFile = rootProject.file("key.properties") + +if (keystorePropertiesFile.exists()) { + FileInputStream(keystorePropertiesFile).use { + keystoreProperties.load(it) + } +} + android { + ndkVersion = flutter.ndkVersion namespace = "com.yimaru.lms.app" compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion + compileOptions { + isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } - kotlin { - compilerOptions { - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) - } - } - defaultConfig { minSdk = flutter.minSdkVersion - applicationId = "com.yimaru.lms.app" versionCode = flutter.versionCode versionName = flutter.versionName + applicationId = "com.yimaru.lms.app" targetSdk = flutter.targetSdkVersion } + signingConfigs { + create("release") { + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storePassword = keystoreProperties["storePassword"] as String + storeFile = keystoreProperties["storeFile"]?.let { file(it as String) } + } + } + buildTypes { - release { - signingConfig = signingConfigs.getByName("debug") + getByName("release") { + isMinifyEnabled = false + isShrinkResources = false + ndk { debugSymbolLevel = "FULL" } + signingConfig = signingConfigs.getByName("release") + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" + ) } } } +kotlin { + jvmToolchain(17) + + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + } +} + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5") + implementation(platform("com.google.firebase:firebase-bom:34.10.0")) +} + flutter { source = "../.." -} +} \ No newline at end of file diff --git a/android/app/google-services.json b/android/app/google-services.json index cd2ee71..56a8b0b 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -14,20 +14,20 @@ }, "oauth_client": [ { - "client_id": "574860813475-01gh5tk0bu5bgj68r02sgh5pk5greoku.apps.googleusercontent.com", - "client_type": 1, - "android_info": { - "package_name": "com.yimaru.lms.app", - "certificate_hash": "fc91f52846d27c62bba3e16bc98982fb9953eca1" - } - }, - { - "client_id": "574860813475-631s3mo8ha2qc2jeb5e2aosn0967niik.apps.googleusercontent.com", + "client_id": "574860813475-3p3k63lkrfd113sn6jscgvdj0aigsg5s.apps.googleusercontent.com", "client_type": 1, "android_info": { "package_name": "com.yimaru.lms.app", "certificate_hash": "928ead08b5e39d6a861a55ae7cceb8c402d1ee7a" } + }, + { + "client_id": "574860813475-m90u87plqaac4tb8oug32k41usossiod.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.yimaru.lms.app", + "certificate_hash": "29797902ad6a24212b9d9fad71562907956f6a6c" + } } ], "api_key": [ diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..378dee0 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,41 @@ +############################################ +# Flutter +############################################ +-keep class io.flutter.** { *; } +-keep class io.flutter.plugins.** { *; } + +############################################ +# Firebase (General Safe Rules) +############################################ +-keep class com.google.firebase.** { *; } +-dontwarn com.google.firebase.** + +############################################ +# Google Sign-In +############################################ +-keep class com.google.android.gms.auth.api.signin.** { *; } +-keep class com.google.android.gms.common.api.** { *; } +-dontwarn com.google.android.gms.** + +############################################ +# Play Services +############################################ +-keep class com.google.android.gms.** { *; } + +############################################ +# flutter_inappwebview +############################################ +-keep class com.pichillilorenzo.flutter_inappwebview.** { *; } +-dontwarn com.pichillilorenzo.flutter_inappwebview.** + +############################################ +# Keep annotations +############################################ +-keepattributes *Annotation* + + +############################################ +# Google Play Core +############################################ +-keep class com.google.android.play.core.** { *; } +-dontwarn com.google.android.play.core.** \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index e39aa8a..bdbb799 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,7 +7,7 @@ - - - - - + + + + + + diff --git a/android/app/src/main/res/drawable-xhdpi/android12splash.png b/android/app/src/main/res/drawable-xhdpi/android12splash.png new file mode 100644 index 0000000..f55494a Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..f55494a Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxhdpi/android12splash.png new file mode 100644 index 0000000..5f92ee4 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..5f92ee4 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png new file mode 100644 index 0000000..39ae533 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..39ae533 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png new file mode 100644 index 0000000..2491c9d Binary files /dev/null and b/android/app/src/main/res/drawable/background.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..3cc4948 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,9 @@ - - - - - + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4..55a59e8 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b7..81ebb40 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 09d4391..1de8ba2 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d..06a7d8d 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372e..303d17e 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml new file mode 100644 index 0000000..a0443bf --- /dev/null +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..dbc9ea9 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + false + false + shortEdges + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..0d1fa8f 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -5,6 +5,10 @@ @drawable/launch_background + false + false + false + shortEdges + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/android/gradle.properties b/android/gradle.properties index fbee1d8..6018dfb 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,2 +1,12 @@ org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true +android.defaults.buildfeatures.resvalues=true +android.sdk.defaultTargetSdkToCompileSdkIfUnset=false +android.enableAppCompileTimeRClass=false +android.usesSdkInManifest.disallowed=false +android.uniquePackageNames=false +android.dependency.useConstraints=true +android.r8.strictFullModeForKeepRules=false +android.r8.optimizedResourceShrinking=false +android.builtInKotlin=false +android.newDsl=false diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e4ef43f..a20f2c4 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 449bbbd..dbbc5c6 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,9 +19,10 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.13.2" apply false + id("com.android.application") version "9.1.0" apply false id("org.jetbrains.kotlin.android") version "2.3.0" apply false id("com.google.gms.google-services") version("4.4.4") apply false + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } diff --git a/assets/icons/duolingo.png b/assets/icons/duolingo.png new file mode 100644 index 0000000..fedca38 Binary files /dev/null and b/assets/icons/duolingo.png differ diff --git a/assets/icons/dwarf.png b/assets/icons/dwarf.png new file mode 100644 index 0000000..e75700b Binary files /dev/null and b/assets/icons/dwarf.png differ diff --git a/assets/icons/splash_logo.png b/assets/icons/splash_logo.png new file mode 100644 index 0000000..2f4bbdf Binary files /dev/null and b/assets/icons/splash_logo.png differ diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json new file mode 100644 index 0000000..9f447e1 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "background.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png new file mode 100644 index 0000000..2491c9d Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json index 0bedcf2..00cabce 100644 --- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -1,23 +1,23 @@ { "images" : [ { - "idiom" : "universal", "filename" : "LaunchImage.png", + "idiom" : "universal", "scale" : "1x" }, { - "idiom" : "universal", "filename" : "LaunchImage@2x.png", + "idiom" : "universal", "scale" : "2x" }, { - "idiom" : "universal", "filename" : "LaunchImage@3x.png", + "idiom" : "universal", "scale" : "3x" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } } diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png index 9da19ea..1385186 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png index 9da19ea..f55494a 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png index 9da19ea..5f92ee4 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard index f2e259c..8d2b7d5 100644 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -16,13 +16,19 @@ - - + + - - + + + + + + + + @@ -32,6 +38,7 @@ - + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index ed66cce..02b00f4 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,49 +1,51 @@ - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Yimaru App - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - yimaru_app - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Yimaru App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + yimaru_app + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + UIStatusBarHidden + + diff --git a/lib/app/app.dart b/lib/app/app.dart index 50af9db..2c6972c 100644 --- a/lib/app/app.dart +++ b/lib/app/app.dart @@ -9,7 +9,6 @@ import 'package:yimaru_app/ui/views/profile/profile_view.dart'; import 'package:yimaru_app/ui/views/profile_detail/profile_detail_view.dart'; import 'package:yimaru_app/ui/views/downloads/downloads_view.dart'; import 'package:yimaru_app/ui/views/progress/progress_view.dart'; -import 'package:yimaru_app/ui/views/ongoing_progress/ongoing_progress_view.dart'; import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart'; import 'package:yimaru_app/ui/views/support/support_view.dart'; import 'package:yimaru_app/ui/views/telegram_support/telegram_support_view.dart'; @@ -30,7 +29,6 @@ import 'package:yimaru_app/services/status_checker_service.dart'; import 'package:yimaru_app/ui/views/welcome/welcome_view.dart'; import 'package:yimaru_app/ui/views/assessment/assessment_view.dart'; import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart'; -import 'package:yimaru_app/ui/views/failure/failure_view.dart'; import 'package:yimaru_app/services/permission_handler_service.dart'; import 'package:yimaru_app/services/image_picker_service.dart'; import 'package:yimaru_app/services/google_auth_service.dart'; @@ -38,6 +36,20 @@ import 'package:yimaru_app/services/image_downloader_service.dart'; import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart'; import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart'; import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'; +import 'package:yimaru_app/ui/views/course_practice/course_practice_view.dart'; +import 'package:yimaru_app/ui/views/course_payment/course_payment_view.dart'; +import 'package:yimaru_app/ui/views/course_category/course_category_view.dart'; +import 'package:yimaru_app/ui/views/failure/failure_view.dart'; +import 'package:yimaru_app/ui/views/course_lesson/course_lesson_view.dart'; +import 'package:yimaru_app/ui/views/course_lesson_detail/course_lesson_detail_view.dart'; +import 'package:yimaru_app/services/notification_service.dart'; +import 'package:yimaru_app/ui/views/duolingo/duolingo_view.dart'; +import 'package:yimaru_app/services/smart_auth_service.dart'; +import 'package:yimaru_app/services/course_service.dart'; +import 'package:yimaru_app/ui/views/course_subcategory/course_subcategory_view.dart'; +import 'package:yimaru_app/ui/views/course/course_view.dart'; +import 'package:yimaru_app/services/audio_player_service.dart'; +import 'package:yimaru_app/services/voice_recorder_service.dart'; // @stacked-import @StackedApp( @@ -49,7 +61,6 @@ import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'; MaterialRoute(page: ProfileDetailView), MaterialRoute(page: DownloadsView), MaterialRoute(page: ProgressView), - MaterialRoute(page: OngoingProgressView), MaterialRoute(page: AccountPrivacyView), MaterialRoute(page: SupportView), MaterialRoute(page: TelegramSupportView), @@ -65,10 +76,18 @@ import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'; MaterialRoute(page: WelcomeView), MaterialRoute(page: AssessmentView), MaterialRoute(page: LearnLessonView), - MaterialRoute(page: FailureView), MaterialRoute(page: ForgetPasswordView), MaterialRoute(page: LearnLessonDetailView), MaterialRoute(page: LearnPracticeView), + MaterialRoute(page: CoursePracticeView), + MaterialRoute(page: CoursePaymentView), + MaterialRoute(page: CourseCategoryView), + MaterialRoute(page: FailureView), + MaterialRoute(page: CourseLessonView), + MaterialRoute(page: CourseLessonDetailView), + MaterialRoute(page: DuolingoView), + MaterialRoute(page: CourseSubcategoryView), + MaterialRoute(page: CourseView), // @stacked-route ], dependencies: [ @@ -84,6 +103,11 @@ import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart'; LazySingleton(classType: ImagePickerService), LazySingleton(classType: GoogleAuthService), LazySingleton(classType: ImageDownloaderService), + LazySingleton(classType: NotificationService), + LazySingleton(classType: SmartAuthService), + LazySingleton(classType: CourseService), + LazySingleton(classType: AudioPlayerService), + LazySingleton(classType: VoiceRecorderService), // @stacked-service ], bottomsheets: [ diff --git a/lib/app/app.locator.dart b/lib/app/app.locator.dart index 77ac6ff..2e05699 100644 --- a/lib/app/app.locator.dart +++ b/lib/app/app.locator.dart @@ -12,14 +12,19 @@ import 'package:stacked_services/src/navigation/navigation_service.dart'; import 'package:stacked_shared/stacked_shared.dart'; import '../services/api_service.dart'; +import '../services/audio_player_service.dart'; import '../services/authentication_service.dart'; +import '../services/course_service.dart'; import '../services/dio_service.dart'; import '../services/google_auth_service.dart'; import '../services/image_downloader_service.dart'; import '../services/image_picker_service.dart'; +import '../services/notification_service.dart'; import '../services/permission_handler_service.dart'; import '../services/secure_storage_service.dart'; +import '../services/smart_auth_service.dart'; import '../services/status_checker_service.dart'; +import '../services/voice_recorder_service.dart'; final locator = StackedLocator.instance; @@ -44,4 +49,9 @@ Future setupLocator({ locator.registerLazySingleton(() => ImagePickerService()); locator.registerLazySingleton(() => GoogleAuthService()); locator.registerLazySingleton(() => ImageDownloaderService()); + locator.registerLazySingleton(() => NotificationService()); + locator.registerLazySingleton(() => SmartAuthService()); + locator.registerLazySingleton(() => CourseService()); + locator.registerLazySingleton(() => AudioPlayerService()); + locator.registerLazySingleton(() => VoiceRecorderService()); } diff --git a/lib/app/app.router.dart b/lib/app/app.router.dart index a6686e2..3d47d9f 100644 --- a/lib/app/app.router.dart +++ b/lib/app/app.router.dart @@ -5,49 +5,65 @@ // ************************************************************************** // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:flutter/material.dart' as _i29; +import 'package:flutter/material.dart' as _i36; import 'package:flutter/material.dart'; import 'package:stacked/stacked.dart' as _i1; -import 'package:stacked_services/stacked_services.dart' as _i30; +import 'package:stacked_services/stacked_services.dart' as _i41; +import 'package:yimaru_app/models/course.dart' as _i37; +import 'package:yimaru_app/models/course_category.dart' as _i39; +import 'package:yimaru_app/models/course_lesson.dart' as _i38; +import 'package:yimaru_app/models/course_subcategory.dart' as _i40; import 'package:yimaru_app/ui/views/account_privacy/account_privacy_view.dart' - as _i10; -import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i23; -import 'package:yimaru_app/ui/views/call_support/call_support_view.dart' - as _i13; -import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7; -import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i25; -import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart' - as _i26; -import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2; -import 'package:yimaru_app/ui/views/language/language_view.dart' as _i14; -import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i19; -import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart' - as _i24; -import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart' - as _i27; -import 'package:yimaru_app/ui/views/learn_level/learn_level_view.dart' as _i20; -import 'package:yimaru_app/ui/views/learn_module/learn_module_view.dart' - as _i21; -import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart' - as _i28; -import 'package:yimaru_app/ui/views/login/login_view.dart' as _i18; -import 'package:yimaru_app/ui/views/onboarding/onboarding_view.dart' as _i3; -import 'package:yimaru_app/ui/views/ongoing_progress/ongoing_progress_view.dart' as _i9; +import 'package:yimaru_app/ui/views/assessment/assessment_view.dart' as _i22; +import 'package:yimaru_app/ui/views/call_support/call_support_view.dart' + as _i12; +import 'package:yimaru_app/ui/views/course/course_view.dart' as _i35; +import 'package:yimaru_app/ui/views/course_category/course_category_view.dart' + as _i29; +import 'package:yimaru_app/ui/views/course_lesson/course_lesson_view.dart' + as _i31; +import 'package:yimaru_app/ui/views/course_lesson_detail/course_lesson_detail_view.dart' + as _i32; +import 'package:yimaru_app/ui/views/course_payment/course_payment_view.dart' + as _i28; +import 'package:yimaru_app/ui/views/course_practice/course_practice_view.dart' + as _i27; +import 'package:yimaru_app/ui/views/course_subcategory/course_subcategory_view.dart' + as _i34; +import 'package:yimaru_app/ui/views/downloads/downloads_view.dart' as _i7; +import 'package:yimaru_app/ui/views/duolingo/duolingo_view.dart' as _i33; +import 'package:yimaru_app/ui/views/failure/failure_view.dart' as _i30; +import 'package:yimaru_app/ui/views/forget_password/forget_password_view.dart' + as _i24; +import 'package:yimaru_app/ui/views/home/home_view.dart' as _i2; +import 'package:yimaru_app/ui/views/language/language_view.dart' as _i13; +import 'package:yimaru_app/ui/views/learn/learn_view.dart' as _i18; +import 'package:yimaru_app/ui/views/learn_lesson/learn_lesson_view.dart' + as _i23; +import 'package:yimaru_app/ui/views/learn_lesson_detail/learn_lesson_detail_view.dart' + as _i25; +import 'package:yimaru_app/ui/views/learn_level/learn_level_view.dart' as _i19; +import 'package:yimaru_app/ui/views/learn_module/learn_module_view.dart' + as _i20; +import 'package:yimaru_app/ui/views/learn_practice/learn_practice_view.dart' + as _i26; +import 'package:yimaru_app/ui/views/login/login_view.dart' as _i17; +import 'package:yimaru_app/ui/views/onboarding/onboarding_view.dart' as _i3; import 'package:yimaru_app/ui/views/privacy_policy/privacy_policy_view.dart' - as _i15; + as _i14; import 'package:yimaru_app/ui/views/profile/profile_view.dart' as _i5; import 'package:yimaru_app/ui/views/profile_detail/profile_detail_view.dart' as _i6; import 'package:yimaru_app/ui/views/progress/progress_view.dart' as _i8; -import 'package:yimaru_app/ui/views/register/register_view.dart' as _i17; +import 'package:yimaru_app/ui/views/register/register_view.dart' as _i16; import 'package:yimaru_app/ui/views/startup/startup_view.dart' as _i4; -import 'package:yimaru_app/ui/views/support/support_view.dart' as _i11; +import 'package:yimaru_app/ui/views/support/support_view.dart' as _i10; import 'package:yimaru_app/ui/views/telegram_support/telegram_support_view.dart' - as _i12; + as _i11; import 'package:yimaru_app/ui/views/terms_and_conditions/terms_and_conditions_view.dart' - as _i16; -import 'package:yimaru_app/ui/views/welcome/welcome_view.dart' as _i22; + as _i15; +import 'package:yimaru_app/ui/views/welcome/welcome_view.dart' as _i21; class Routes { static const homeView = '/home-view'; @@ -64,8 +80,6 @@ class Routes { static const progressView = '/progress-view'; - static const ongoingProgressView = '/ongoing-progress-view'; - static const accountPrivacyView = '/account-privacy-view'; static const supportView = '/support-view'; @@ -96,14 +110,30 @@ class Routes { static const learnLessonView = '/learn-lesson-view'; - static const failureView = '/failure-view'; - static const forgetPasswordView = '/forget-password-view'; static const learnLessonDetailView = '/learn-lesson-detail-view'; static const learnPracticeView = '/learn-practice-view'; + static const coursePracticeView = '/course-practice-view'; + + static const coursePaymentView = '/course-payment-view'; + + static const courseCategoryView = '/course-category-view'; + + static const failureView = '/failure-view'; + + static const courseLessonView = '/course-lesson-view'; + + static const courseLessonDetailView = '/course-lesson-detail-view'; + + static const duolingoView = '/duolingo-view'; + + static const courseSubcategoryView = '/course-subcategory-view'; + + static const courseView = '/course-view'; + static const all = { homeView, onboardingView, @@ -112,7 +142,6 @@ class Routes { profileDetailView, downloadsView, progressView, - ongoingProgressView, accountPrivacyView, supportView, telegramSupportView, @@ -128,10 +157,18 @@ class Routes { welcomeView, assessmentView, learnLessonView, - failureView, forgetPasswordView, learnLessonDetailView, learnPracticeView, + coursePracticeView, + coursePaymentView, + courseCategoryView, + failureView, + courseLessonView, + courseLessonDetailView, + duolingoView, + courseSubcategoryView, + courseView, }; } @@ -165,97 +202,125 @@ class StackedRouter extends _i1.RouterBase { Routes.progressView, page: _i8.ProgressView, ), - _i1.RouteDef( - Routes.ongoingProgressView, - page: _i9.OngoingProgressView, - ), _i1.RouteDef( Routes.accountPrivacyView, - page: _i10.AccountPrivacyView, + page: _i9.AccountPrivacyView, ), _i1.RouteDef( Routes.supportView, - page: _i11.SupportView, + page: _i10.SupportView, ), _i1.RouteDef( Routes.telegramSupportView, - page: _i12.TelegramSupportView, + page: _i11.TelegramSupportView, ), _i1.RouteDef( Routes.callSupportView, - page: _i13.CallSupportView, + page: _i12.CallSupportView, ), _i1.RouteDef( Routes.languageView, - page: _i14.LanguageView, + page: _i13.LanguageView, ), _i1.RouteDef( Routes.privacyPolicyView, - page: _i15.PrivacyPolicyView, + page: _i14.PrivacyPolicyView, ), _i1.RouteDef( Routes.termsAndConditionsView, - page: _i16.TermsAndConditionsView, + page: _i15.TermsAndConditionsView, ), _i1.RouteDef( Routes.registerView, - page: _i17.RegisterView, + page: _i16.RegisterView, ), _i1.RouteDef( Routes.loginView, - page: _i18.LoginView, + page: _i17.LoginView, ), _i1.RouteDef( Routes.learnView, - page: _i19.LearnView, + page: _i18.LearnView, ), _i1.RouteDef( Routes.learnLevelView, - page: _i20.LearnLevelView, + page: _i19.LearnLevelView, ), _i1.RouteDef( Routes.learnModuleView, - page: _i21.LearnModuleView, + page: _i20.LearnModuleView, ), _i1.RouteDef( Routes.welcomeView, - page: _i22.WelcomeView, + page: _i21.WelcomeView, ), _i1.RouteDef( Routes.assessmentView, - page: _i23.AssessmentView, + page: _i22.AssessmentView, ), _i1.RouteDef( Routes.learnLessonView, - page: _i24.LearnLessonView, - ), - _i1.RouteDef( - Routes.failureView, - page: _i25.FailureView, + page: _i23.LearnLessonView, ), _i1.RouteDef( Routes.forgetPasswordView, - page: _i26.ForgetPasswordView, + page: _i24.ForgetPasswordView, ), _i1.RouteDef( Routes.learnLessonDetailView, - page: _i27.LearnLessonDetailView, + page: _i25.LearnLessonDetailView, ), _i1.RouteDef( Routes.learnPracticeView, - page: _i28.LearnPracticeView, + page: _i26.LearnPracticeView, + ), + _i1.RouteDef( + Routes.coursePracticeView, + page: _i27.CoursePracticeView, + ), + _i1.RouteDef( + Routes.coursePaymentView, + page: _i28.CoursePaymentView, + ), + _i1.RouteDef( + Routes.courseCategoryView, + page: _i29.CourseCategoryView, + ), + _i1.RouteDef( + Routes.failureView, + page: _i30.FailureView, + ), + _i1.RouteDef( + Routes.courseLessonView, + page: _i31.CourseLessonView, + ), + _i1.RouteDef( + Routes.courseLessonDetailView, + page: _i32.CourseLessonDetailView, + ), + _i1.RouteDef( + Routes.duolingoView, + page: _i33.DuolingoView, + ), + _i1.RouteDef( + Routes.courseSubcategoryView, + page: _i34.CourseSubcategoryView, + ), + _i1.RouteDef( + Routes.courseView, + page: _i35.CourseView, ), ]; final _pagesMap = { _i2.HomeView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i2.HomeView(), settings: data, ); }, _i3.OnboardingView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i3.OnboardingView(), settings: data, ); @@ -264,156 +329,228 @@ class StackedRouter extends _i1.RouterBase { final args = data.getArgs( orElse: () => const StartupViewArguments(), ); - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => _i4.StartupView(key: args.key, label: args.label), settings: data, ); }, _i5.ProfileView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i5.ProfileView(), settings: data, ); }, _i6.ProfileDetailView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i6.ProfileDetailView(), settings: data, ); }, _i7.DownloadsView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i7.DownloadsView(), settings: data, ); }, _i8.ProgressView: (data) { - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => const _i8.ProgressView(), settings: data, ); }, - _i9.OngoingProgressView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i9.OngoingProgressView(), + _i9.AccountPrivacyView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i9.AccountPrivacyView(), settings: data, ); }, - _i10.AccountPrivacyView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i10.AccountPrivacyView(), + _i10.SupportView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i10.SupportView(), settings: data, ); }, - _i11.SupportView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i11.SupportView(), + _i11.TelegramSupportView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i11.TelegramSupportView(), settings: data, ); }, - _i12.TelegramSupportView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i12.TelegramSupportView(), + _i12.CallSupportView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i12.CallSupportView(), settings: data, ); }, - _i13.CallSupportView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i13.CallSupportView(), + _i13.LanguageView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i13.LanguageView(), settings: data, ); }, - _i14.LanguageView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i14.LanguageView(), + _i14.PrivacyPolicyView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i14.PrivacyPolicyView(), settings: data, ); }, - _i15.PrivacyPolicyView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i15.PrivacyPolicyView(), + _i15.TermsAndConditionsView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i15.TermsAndConditionsView(), settings: data, ); }, - _i16.TermsAndConditionsView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i16.TermsAndConditionsView(), + _i16.RegisterView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i16.RegisterView(), settings: data, ); }, - _i17.RegisterView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i17.RegisterView(), + _i17.LoginView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i17.LoginView(), settings: data, ); }, - _i18.LoginView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i18.LoginView(), + _i18.LearnView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i18.LearnView(), settings: data, ); }, - _i19.LearnView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i19.LearnView(), + _i19.LearnLevelView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i19.LearnLevelView(), settings: data, ); }, - _i20.LearnLevelView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i20.LearnLevelView(), + _i20.LearnModuleView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i20.LearnModuleView(), settings: data, ); }, - _i21.LearnModuleView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i21.LearnModuleView(), + _i21.WelcomeView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i21.WelcomeView(), settings: data, ); }, - _i22.WelcomeView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i22.WelcomeView(), - settings: data, - ); - }, - _i23.AssessmentView: (data) { + _i22.AssessmentView: (data) { final args = data.getArgs(nullOk: false); - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => - _i23.AssessmentView(key: args.key, data: args.data), + _i22.AssessmentView(key: args.key, data: args.data), settings: data, ); }, - _i24.LearnLessonView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i24.LearnLessonView(), + _i23.LearnLessonView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => _i23.LearnLessonView( + key: args.key, + title: args.title, + topics: args.topics, + subtitle: args.subtitle, + practices: args.practices, + description: args.description), settings: data, ); }, - _i25.FailureView: (data) { + _i24.ForgetPasswordView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i24.ForgetPasswordView(), + settings: data, + ); + }, + _i25.LearnLessonDetailView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => _i25.LearnLessonDetailView( + key: args.key, + title: args.title, + practices: args.practices, + description: args.description), + settings: data, + ); + }, + _i26.LearnPracticeView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => _i26.LearnPracticeView( + key: args.key, + title: args.title, + subtitle: args.subtitle, + practices: args.practices, + buttonLabel: args.buttonLabel), + settings: data, + ); + }, + _i27.CoursePracticeView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i27.CoursePracticeView(key: args.key, id: args.id), + settings: data, + ); + }, + _i28.CoursePaymentView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i28.CoursePaymentView(key: args.key, course: args.course), + settings: data, + ); + }, + _i29.CourseCategoryView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i29.CourseCategoryView(), + settings: data, + ); + }, + _i30.FailureView: (data) { final args = data.getArgs(nullOk: false); - return _i29.MaterialPageRoute( + return _i36.MaterialPageRoute( builder: (context) => - _i25.FailureView(key: args.key, label: args.label), + _i30.FailureView(key: args.key, label: args.label), settings: data, ); }, - _i26.ForgetPasswordView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i26.ForgetPasswordView(), + _i31.CourseLessonView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i31.CourseLessonView(key: args.key, course: args.course), settings: data, ); }, - _i27.LearnLessonDetailView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i27.LearnLessonDetailView(), + _i32.CourseLessonDetailView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i32.CourseLessonDetailView(key: args.key, lesson: args.lesson), settings: data, ); }, - _i28.LearnPracticeView: (data) { - return _i29.MaterialPageRoute( - builder: (context) => const _i28.LearnPracticeView(), + _i33.DuolingoView: (data) { + return _i36.MaterialPageRoute( + builder: (context) => const _i33.DuolingoView(), + settings: data, + ); + }, + _i34.CourseSubcategoryView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i34.CourseSubcategoryView(key: args.key, category: args.category), + settings: data, + ); + }, + _i35.CourseView: (data) { + final args = data.getArgs(nullOk: false); + return _i36.MaterialPageRoute( + builder: (context) => + _i35.CourseView(key: args.key, subcategory: args.subcategory), settings: data, ); }, @@ -432,7 +569,7 @@ class StartupViewArguments { this.label = 'Loading', }); - final _i29.Key? key; + final _i36.Key? key; final String label; @@ -459,7 +596,7 @@ class AssessmentViewArguments { required this.data, }); - final _i29.Key? key; + final _i36.Key? key; final Map data; @@ -480,13 +617,199 @@ class AssessmentViewArguments { } } +class LearnLessonViewArguments { + const LearnLessonViewArguments({ + this.key, + required this.title, + required this.topics, + required this.subtitle, + required this.practices, + required this.description, + }); + + final _i36.Key? key; + + final String title; + + final String topics; + + final String subtitle; + + final List> practices; + + final String description; + + @override + String toString() { + return '{"key": "$key", "title": "$title", "topics": "$topics", "subtitle": "$subtitle", "practices": "$practices", "description": "$description"}'; + } + + @override + bool operator ==(covariant LearnLessonViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && + other.title == title && + other.topics == topics && + other.subtitle == subtitle && + other.practices == practices && + other.description == description; + } + + @override + int get hashCode { + return key.hashCode ^ + title.hashCode ^ + topics.hashCode ^ + subtitle.hashCode ^ + practices.hashCode ^ + description.hashCode; + } +} + +class LearnLessonDetailViewArguments { + const LearnLessonDetailViewArguments({ + this.key, + required this.title, + required this.practices, + required this.description, + }); + + final _i36.Key? key; + + final String title; + + final List> practices; + + final String description; + + @override + String toString() { + return '{"key": "$key", "title": "$title", "practices": "$practices", "description": "$description"}'; + } + + @override + bool operator ==(covariant LearnLessonDetailViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && + other.title == title && + other.practices == practices && + other.description == description; + } + + @override + int get hashCode { + return key.hashCode ^ + title.hashCode ^ + practices.hashCode ^ + description.hashCode; + } +} + +class LearnPracticeViewArguments { + const LearnPracticeViewArguments({ + this.key, + required this.title, + required this.subtitle, + required this.practices, + required this.buttonLabel, + }); + + final _i36.Key? key; + + final String title; + + final String subtitle; + + final List> practices; + + final String buttonLabel; + + @override + String toString() { + return '{"key": "$key", "title": "$title", "subtitle": "$subtitle", "practices": "$practices", "buttonLabel": "$buttonLabel"}'; + } + + @override + bool operator ==(covariant LearnPracticeViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && + other.title == title && + other.subtitle == subtitle && + other.practices == practices && + other.buttonLabel == buttonLabel; + } + + @override + int get hashCode { + return key.hashCode ^ + title.hashCode ^ + subtitle.hashCode ^ + practices.hashCode ^ + buttonLabel.hashCode; + } +} + +class CoursePracticeViewArguments { + const CoursePracticeViewArguments({ + this.key, + required this.id, + }); + + final _i36.Key? key; + + final int id; + + @override + String toString() { + return '{"key": "$key", "id": "$id"}'; + } + + @override + bool operator ==(covariant CoursePracticeViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.id == id; + } + + @override + int get hashCode { + return key.hashCode ^ id.hashCode; + } +} + +class CoursePaymentViewArguments { + const CoursePaymentViewArguments({ + this.key, + required this.course, + }); + + final _i36.Key? key; + + final _i37.Course course; + + @override + String toString() { + return '{"key": "$key", "course": "$course"}'; + } + + @override + bool operator ==(covariant CoursePaymentViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.course == course; + } + + @override + int get hashCode { + return key.hashCode ^ course.hashCode; + } +} + class FailureViewArguments { const FailureViewArguments({ this.key, required this.label, }); - final _i29.Key? key; + final _i36.Key? key; final String label; @@ -507,7 +830,115 @@ class FailureViewArguments { } } -extension NavigatorStateExtension on _i30.NavigationService { +class CourseLessonViewArguments { + const CourseLessonViewArguments({ + this.key, + required this.course, + }); + + final _i36.Key? key; + + final _i37.Course course; + + @override + String toString() { + return '{"key": "$key", "course": "$course"}'; + } + + @override + bool operator ==(covariant CourseLessonViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.course == course; + } + + @override + int get hashCode { + return key.hashCode ^ course.hashCode; + } +} + +class CourseLessonDetailViewArguments { + const CourseLessonDetailViewArguments({ + this.key, + required this.lesson, + }); + + final _i36.Key? key; + + final _i38.CourseLesson lesson; + + @override + String toString() { + return '{"key": "$key", "lesson": "$lesson"}'; + } + + @override + bool operator ==(covariant CourseLessonDetailViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.lesson == lesson; + } + + @override + int get hashCode { + return key.hashCode ^ lesson.hashCode; + } +} + +class CourseSubcategoryViewArguments { + const CourseSubcategoryViewArguments({ + this.key, + required this.category, + }); + + final _i36.Key? key; + + final _i39.CourseCategory category; + + @override + String toString() { + return '{"key": "$key", "category": "$category"}'; + } + + @override + bool operator ==(covariant CourseSubcategoryViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.category == category; + } + + @override + int get hashCode { + return key.hashCode ^ category.hashCode; + } +} + +class CourseViewArguments { + const CourseViewArguments({ + this.key, + required this.subcategory, + }); + + final _i36.Key? key; + + final _i40.CourseSubcategory subcategory; + + @override + String toString() { + return '{"key": "$key", "subcategory": "$subcategory"}'; + } + + @override + bool operator ==(covariant CourseViewArguments other) { + if (identical(this, other)) return true; + return other.key == key && other.subcategory == subcategory; + } + + @override + int get hashCode { + return key.hashCode ^ subcategory.hashCode; + } +} + +extension NavigatorStateExtension on _i41.NavigationService { Future navigateToHomeView([ int? routerId, bool preventDuplicates = true, @@ -537,7 +968,7 @@ extension NavigatorStateExtension on _i30.NavigationService { } Future navigateToStartupView({ - _i29.Key? key, + _i36.Key? key, String label = 'Loading', int? routerId, bool preventDuplicates = true, @@ -609,20 +1040,6 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future navigateToOngoingProgressView([ - int? routerId, - bool preventDuplicates = true, - Map? parameters, - Widget Function(BuildContext, Animation, Animation, Widget)? - transition, - ]) async { - return navigateTo(Routes.ongoingProgressView, - id: routerId, - preventDuplicates: preventDuplicates, - parameters: parameters, - transition: transition); - } - Future navigateToAccountPrivacyView([ int? routerId, bool preventDuplicates = true, @@ -806,7 +1223,7 @@ extension NavigatorStateExtension on _i30.NavigationService { } Future navigateToAssessmentView({ - _i29.Key? key, + _i36.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -822,31 +1239,27 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future navigateToLearnLessonView([ - int? routerId, - bool preventDuplicates = true, - Map? parameters, - Widget Function(BuildContext, Animation, Animation, Widget)? - transition, - ]) async { - return navigateTo(Routes.learnLessonView, - id: routerId, - preventDuplicates: preventDuplicates, - parameters: parameters, - transition: transition); - } - - Future navigateToFailureView({ - _i29.Key? key, - required String label, + Future navigateToLearnLessonView({ + _i36.Key? key, + required String title, + required String topics, + required String subtitle, + required List> practices, + required String description, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, }) async { - return navigateTo(Routes.failureView, - arguments: FailureViewArguments(key: key, label: label), + return navigateTo(Routes.learnLessonView, + arguments: LearnLessonViewArguments( + key: key, + title: title, + topics: topics, + subtitle: subtitle, + practices: practices, + description: description), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, @@ -867,28 +1280,195 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future navigateToLearnLessonDetailView([ + Future navigateToLearnLessonDetailView({ + _i36.Key? key, + required String title, + required List> practices, + required String description, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, - ]) async { + }) async { return navigateTo(Routes.learnLessonDetailView, + arguments: LearnLessonDetailViewArguments( + key: key, + title: title, + practices: practices, + description: description), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, transition: transition); } - Future navigateToLearnPracticeView([ + Future navigateToLearnPracticeView({ + _i36.Key? key, + required String title, + required String subtitle, + required List> practices, + required String buttonLabel, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.learnPracticeView, + arguments: LearnPracticeViewArguments( + key: key, + title: title, + subtitle: subtitle, + practices: practices, + buttonLabel: buttonLabel), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCoursePracticeView({ + _i36.Key? key, + required int id, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.coursePracticeView, + arguments: CoursePracticeViewArguments(key: key, id: id), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCoursePaymentView({ + _i36.Key? key, + required _i37.Course course, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.coursePaymentView, + arguments: CoursePaymentViewArguments(key: key, course: course), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCourseCategoryView([ int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, ]) async { - return navigateTo(Routes.learnPracticeView, + return navigateTo(Routes.courseCategoryView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToFailureView({ + _i36.Key? key, + required String label, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.failureView, + arguments: FailureViewArguments(key: key, label: label), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCourseLessonView({ + _i36.Key? key, + required _i37.Course course, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.courseLessonView, + arguments: CourseLessonViewArguments(key: key, course: course), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCourseLessonDetailView({ + _i36.Key? key, + required _i38.CourseLesson lesson, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.courseLessonDetailView, + arguments: CourseLessonDetailViewArguments(key: key, lesson: lesson), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToDuolingoView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return navigateTo(Routes.duolingoView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCourseSubcategoryView({ + _i36.Key? key, + required _i39.CourseCategory category, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.courseSubcategoryView, + arguments: CourseSubcategoryViewArguments(key: key, category: category), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future navigateToCourseView({ + _i36.Key? key, + required _i40.CourseSubcategory subcategory, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return navigateTo(Routes.courseView, + arguments: CourseViewArguments(key: key, subcategory: subcategory), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, @@ -924,7 +1504,7 @@ extension NavigatorStateExtension on _i30.NavigationService { } Future replaceWithStartupView({ - _i29.Key? key, + _i36.Key? key, String label = 'Loading', int? routerId, bool preventDuplicates = true, @@ -996,20 +1576,6 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future replaceWithOngoingProgressView([ - int? routerId, - bool preventDuplicates = true, - Map? parameters, - Widget Function(BuildContext, Animation, Animation, Widget)? - transition, - ]) async { - return replaceWith(Routes.ongoingProgressView, - id: routerId, - preventDuplicates: preventDuplicates, - parameters: parameters, - transition: transition); - } - Future replaceWithAccountPrivacyView([ int? routerId, bool preventDuplicates = true, @@ -1193,7 +1759,7 @@ extension NavigatorStateExtension on _i30.NavigationService { } Future replaceWithAssessmentView({ - _i29.Key? key, + _i36.Key? key, required Map data, int? routerId, bool preventDuplicates = true, @@ -1209,31 +1775,27 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future replaceWithLearnLessonView([ - int? routerId, - bool preventDuplicates = true, - Map? parameters, - Widget Function(BuildContext, Animation, Animation, Widget)? - transition, - ]) async { - return replaceWith(Routes.learnLessonView, - id: routerId, - preventDuplicates: preventDuplicates, - parameters: parameters, - transition: transition); - } - - Future replaceWithFailureView({ - _i29.Key? key, - required String label, + Future replaceWithLearnLessonView({ + _i36.Key? key, + required String title, + required String topics, + required String subtitle, + required List> practices, + required String description, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, }) async { - return replaceWith(Routes.failureView, - arguments: FailureViewArguments(key: key, label: label), + return replaceWith(Routes.learnLessonView, + arguments: LearnLessonViewArguments( + key: key, + title: title, + topics: topics, + subtitle: subtitle, + practices: practices, + description: description), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, @@ -1254,28 +1816,195 @@ extension NavigatorStateExtension on _i30.NavigationService { transition: transition); } - Future replaceWithLearnLessonDetailView([ + Future replaceWithLearnLessonDetailView({ + _i36.Key? key, + required String title, + required List> practices, + required String description, int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, - ]) async { + }) async { return replaceWith(Routes.learnLessonDetailView, + arguments: LearnLessonDetailViewArguments( + key: key, + title: title, + practices: practices, + description: description), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, transition: transition); } - Future replaceWithLearnPracticeView([ + Future replaceWithLearnPracticeView({ + _i36.Key? key, + required String title, + required String subtitle, + required List> practices, + required String buttonLabel, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.learnPracticeView, + arguments: LearnPracticeViewArguments( + key: key, + title: title, + subtitle: subtitle, + practices: practices, + buttonLabel: buttonLabel), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCoursePracticeView({ + _i36.Key? key, + required int id, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.coursePracticeView, + arguments: CoursePracticeViewArguments(key: key, id: id), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCoursePaymentView({ + _i36.Key? key, + required _i37.Course course, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.coursePaymentView, + arguments: CoursePaymentViewArguments(key: key, course: course), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCourseCategoryView([ int? routerId, bool preventDuplicates = true, Map? parameters, Widget Function(BuildContext, Animation, Animation, Widget)? transition, ]) async { - return replaceWith(Routes.learnPracticeView, + return replaceWith(Routes.courseCategoryView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithFailureView({ + _i36.Key? key, + required String label, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.failureView, + arguments: FailureViewArguments(key: key, label: label), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCourseLessonView({ + _i36.Key? key, + required _i37.Course course, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.courseLessonView, + arguments: CourseLessonViewArguments(key: key, course: course), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCourseLessonDetailView({ + _i36.Key? key, + required _i38.CourseLesson lesson, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.courseLessonDetailView, + arguments: CourseLessonDetailViewArguments(key: key, lesson: lesson), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithDuolingoView([ + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + ]) async { + return replaceWith(Routes.duolingoView, + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCourseSubcategoryView({ + _i36.Key? key, + required _i39.CourseCategory category, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.courseSubcategoryView, + arguments: CourseSubcategoryViewArguments(key: key, category: category), + id: routerId, + preventDuplicates: preventDuplicates, + parameters: parameters, + transition: transition); + } + + Future replaceWithCourseView({ + _i36.Key? key, + required _i40.CourseSubcategory subcategory, + int? routerId, + bool preventDuplicates = true, + Map? parameters, + Widget Function(BuildContext, Animation, Animation, Widget)? + transition, + }) async { + return replaceWith(Routes.courseView, + arguments: CourseViewArguments(key: key, subcategory: subcategory), id: routerId, preventDuplicates: preventDuplicates, parameters: parameters, diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index f2470b8..27ce554 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -64,7 +64,7 @@ class DefaultFirebaseOptions { projectId: 'yimaru-lms-e834e', storageBucket: 'yimaru-lms-e834e.firebasestorage.app', androidClientId: - '574860813475-01gh5tk0bu5bgj68r02sgh5pk5greoku.apps.googleusercontent.com', + '574860813475-3p3k63lkrfd113sn6jscgvdj0aigsg5s.apps.googleusercontent.com', iosBundleId: 'com.yimaru.lms.app', ); } diff --git a/lib/main.dart b/lib/main.dart index c3f54fc..6031bc0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:toastification/toastification.dart'; import 'package:yimaru_app/app/app.bottomsheets.dart'; @@ -5,10 +6,15 @@ import 'package:yimaru_app/app/app.dialogs.dart'; import 'package:yimaru_app/app/app.locator.dart'; import 'package:yimaru_app/app/app.router.dart'; import 'package:stacked_services/stacked_services.dart'; +import 'package:yimaru_app/services/notification_service.dart'; + +import 'firebase_options.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await setupLocator(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + await locator().initialize(); setupDialogUi(); setupBottomSheetUi(); runApp(const MainApp()); diff --git a/lib/models/assessment.dart b/lib/models/assessment.dart index 9a6da65..082ce80 100644 --- a/lib/models/assessment.dart +++ b/lib/models/assessment.dart @@ -10,6 +10,8 @@ class Assessment { final String? status; + final List