From 5aaa4a0d643f303fc529e6ac5017d281578484b3 Mon Sep 17 00:00:00 2001 From: machuanyu <840649825@qq.com> Date: Mon, 1 Apr 2024 10:49:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .fvm/flutter_sdk | 1 + .fvm/fvm_config.json | 4 + .gitignore | 63 +- .metadata | 33 + README.md | 17 +- analysis_options.yaml | 29 + android/.gitignore | 13 + android/app/build.gradle | 73 ++ android/app/src/debug/AndroidManifest.xml | 7 + android/app/src/main/AndroidManifest.xml | 33 + .../school_asignment_app/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + android/app/src/main/res/values/styles.xml | 18 + android/app/src/profile/AndroidManifest.xml | 7 + android/build.gradle | 31 + android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + android/settings.gradle | 11 + assets/images/login_bgi.png | Bin 0 -> 35758 bytes assets/images/logo.png | Bin 0 -> 6257 bytes ios/.gitignore | 34 + ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Runner.xcodeproj/project.pbxproj | 613 ++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 98 ++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 + ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 51 + ios/Runner/Runner-Bridging-Header.h | 1 + ios/RunnerTests/RunnerTests.swift | 12 + lib/common/api/user_api.dart | 19 + lib/common/config/app_config.dart | 18 + lib/common/config/colorUtils.dart | 53 ++ lib/common/const_text.dart | 36 + lib/common/job/common/base_page.dart | 31 + lib/common/job/common/base_page.g.dart | 17 + lib/common/job/common/base_page_data.dart | 29 + lib/common/job/common/base_page_data.g.dart | 25 + .../job/common/base_page_data_report.dart | 19 + .../job/common/base_page_data_report.g.dart | 25 + lib/common/job/common/base_page_report.dart | 31 + lib/common/job/common/base_page_report.g.dart | 19 + .../job/common/base_structure_result.dart | 38 + .../job/common/base_structure_result.g.dart | 41 + .../common/base_structure_result_report.dart | 38 + .../base_structure_result_report.g.dart | 41 + .../job/common/upload_img_secret_key.dart | 57 ++ .../job/common/upload_img_secret_key.g.dart | 45 + lib/common/job/user_info.dart | 53 ++ lib/common/job/user_info.g.dart | 41 + lib/common/job/user_login.dart | 32 + lib/common/job/user_login.g.dart | 31 + lib/common/request/request_config.dart | 80 ++ lib/common/request/rest_dio.dart | 427 +++++++++ lib/common/store/app_storage_key.dart | 15 + lib/common/store/user_store.dart | 48 + lib/common/the_global.dart | 6 + lib/common/utils/common_utils.dart | 21 + lib/common/utils/storage.dart | 30 + lib/common/utils/toast_utils.dart | 82 ++ lib/common/utils/utils.dart | 17 + lib/main.dart | 164 ++++ lib/page/global_widget/my_text.dart | 33 + lib/page/global_widget/start_page.dart | 58 ++ lib/page/home_page/home_binding.dart | 10 + lib/page/home_page/home_logic.dart | 7 + lib/page/home_page/home_state.dart | 5 + lib/page/home_page/home_view.dart | 45 + .../login_page/children/agreement_page.dart | 30 + lib/page/login_page/login_binding.dart | 10 + lib/page/login_page/login_logic.dart | 148 +++ lib/page/login_page/login_state.dart | 19 + lib/page/login_page/login_view.dart | 304 ++++++ lib/routes/app_pages.dart | 16 + lib/routes/app_routes.dart | 8 + pubspec.lock | 882 ++++++++++++++++++ pubspec.yaml | 123 +++ test/widget_test.dart | 30 + 114 files changed, 4833 insertions(+), 29 deletions(-) create mode 160000 .fvm/flutter_sdk create mode 100644 .fvm/fvm_config.json create mode 100644 .metadata create mode 100644 analysis_options.yaml create mode 100644 android/.gitignore create mode 100644 android/app/build.gradle create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/kotlin/com/example/school_asignment_app/MainActivity.kt create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values-night/styles.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle create mode 100644 assets/images/login_bgi.png create mode 100644 assets/images/logo.png create mode 100644 ios/.gitignore create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.swift create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/Runner-Bridging-Header.h create mode 100644 ios/RunnerTests/RunnerTests.swift create mode 100644 lib/common/api/user_api.dart create mode 100644 lib/common/config/app_config.dart create mode 100644 lib/common/config/colorUtils.dart create mode 100644 lib/common/const_text.dart create mode 100644 lib/common/job/common/base_page.dart create mode 100644 lib/common/job/common/base_page.g.dart create mode 100644 lib/common/job/common/base_page_data.dart create mode 100644 lib/common/job/common/base_page_data.g.dart create mode 100644 lib/common/job/common/base_page_data_report.dart create mode 100644 lib/common/job/common/base_page_data_report.g.dart create mode 100644 lib/common/job/common/base_page_report.dart create mode 100644 lib/common/job/common/base_page_report.g.dart create mode 100644 lib/common/job/common/base_structure_result.dart create mode 100644 lib/common/job/common/base_structure_result.g.dart create mode 100644 lib/common/job/common/base_structure_result_report.dart create mode 100644 lib/common/job/common/base_structure_result_report.g.dart create mode 100644 lib/common/job/common/upload_img_secret_key.dart create mode 100644 lib/common/job/common/upload_img_secret_key.g.dart create mode 100644 lib/common/job/user_info.dart create mode 100644 lib/common/job/user_info.g.dart create mode 100644 lib/common/job/user_login.dart create mode 100644 lib/common/job/user_login.g.dart create mode 100644 lib/common/request/request_config.dart create mode 100644 lib/common/request/rest_dio.dart create mode 100644 lib/common/store/app_storage_key.dart create mode 100644 lib/common/store/user_store.dart create mode 100644 lib/common/the_global.dart create mode 100644 lib/common/utils/common_utils.dart create mode 100644 lib/common/utils/storage.dart create mode 100644 lib/common/utils/toast_utils.dart create mode 100644 lib/common/utils/utils.dart create mode 100644 lib/main.dart create mode 100644 lib/page/global_widget/my_text.dart create mode 100644 lib/page/global_widget/start_page.dart create mode 100644 lib/page/home_page/home_binding.dart create mode 100644 lib/page/home_page/home_logic.dart create mode 100644 lib/page/home_page/home_state.dart create mode 100644 lib/page/home_page/home_view.dart create mode 100644 lib/page/login_page/children/agreement_page.dart create mode 100644 lib/page/login_page/login_binding.dart create mode 100644 lib/page/login_page/login_logic.dart create mode 100644 lib/page/login_page/login_state.dart create mode 100644 lib/page/login_page/login_view.dart create mode 100644 lib/routes/app_pages.dart create mode 100644 lib/routes/app_routes.dart create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 test/widget_test.dart diff --git a/.fvm/flutter_sdk b/.fvm/flutter_sdk new file mode 160000 index 0000000..d3d8eff --- /dev/null +++ b/.fvm/flutter_sdk @@ -0,0 +1 @@ +Subproject commit d3d8effc686d73e0114d71abdcccef63fa1f25d2 diff --git a/.fvm/fvm_config.json b/.fvm/fvm_config.json new file mode 100644 index 0000000..9474807 --- /dev/null +++ b/.fvm/fvm_config.json @@ -0,0 +1,4 @@ +{ + "flutterSdkVersion": "3.10.1", + "flavors": {} +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a8b0d1d..24476c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,44 @@ -# ---> Android -# Gradle files -.gradle/ -build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Log/OS Files +# Miscellaneous +*.class *.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ -# Android Studio generated files and folders -captures/ -.externalNativeBuild/ -.cxx/ -*.apk -output.json - -# IntelliJ +# IntelliJ related *.iml +*.ipr +*.iws .idea/ -misc.xml -deploymentTargetDropDown.xml -render.experimental.xml -# Keystore files -*.jks -*.keystore +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ -# Google Services (e.g. APIs or Firebase) -google-services.json +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ -# Android Profiling -*.hprof +# Symbolication related +app.*.symbols +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..14f5fc9 --- /dev/null +++ b/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + - platform: android + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + - platform: ios + create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md index 8146f0a..4e3f781 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,16 @@ -# Making.School.Asignment.app +# school_asignment_app -阅卷App第二版 \ No newline at end of file +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..69c3399 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,73 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + namespace "com.example.school_asignment_app" + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.school_asignment_app" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +// minSdkVersion flutter.minSdkVersion + minSdkVersion 21 + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a36daaf --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/school_asignment_app/MainActivity.kt b/android/app/src/main/kotlin/com/example/school_asignment_app/MainActivity.kt new file mode 100644 index 0000000..bee54ec --- /dev/null +++ b/android/app/src/main/kotlin/com/example/school_asignment_app/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.school_asignment_app + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..f7eb7f6 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.3.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..3c472b9 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/images/login_bgi.png b/assets/images/login_bgi.png new file mode 100644 index 0000000000000000000000000000000000000000..d102c3c8a8efc516dde9e326c6f7770e55c4324f GIT binary patch literal 35758 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 literal 0 HcmV?d00001 diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c50a5e2c90a95acf9a08ddcf299a6b5301c46776 GIT binary patch literal 6257 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 bW9|O~%f%PiNG^GT00000NkvXXu0mjfA)fS} literal 0 HcmV?d00001 diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..27e7203 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,613 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807E294A63A400263BE5 /* Frameworks */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AE0B7B92F70575B8D7E0D07E /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89B67EB44CE7B6631473024E /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 640959BDD8F10B91D80A66BE /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.schoolAsignmentApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..e42adcb --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..c47d46a --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + School Asignment App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + school_asignment_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 + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/common/api/user_api.dart b/lib/common/api/user_api.dart new file mode 100644 index 0000000..ba1a158 --- /dev/null +++ b/lib/common/api/user_api.dart @@ -0,0 +1,19 @@ +import 'package:school_asignment_app/common/job/user_info.dart'; +import 'package:school_asignment_app/common/request/rest_dio.dart'; + +import '../job/common/base_structure_result.dart'; + +class UserApi{ + static Future> toLogin({required String loginName, required String password}) async { + var response = await RestDio.instance.post('/auth/login/exam-marking/user', data: {'loginName': loginName,'password': password}); + return BaseStructureResult.fromJson(response, (response) => response); + } + + // 获取用户信息 + static Future> getUserInfo() async { + var response = await RestDio.instance.get('/auth/info/cur-user'); + return BaseStructureResult.fromJson(response, (response) => UserInfo.fromJson(response)); + } + + +} \ No newline at end of file diff --git a/lib/common/config/app_config.dart b/lib/common/config/app_config.dart new file mode 100644 index 0000000..fa82751 --- /dev/null +++ b/lib/common/config/app_config.dart @@ -0,0 +1,18 @@ +// ignore_for_file: constant_identifier_names + +library values; + +/// +/// 项目常量配置 +/// + +class AppConfig { + static const bool DEBUG_MODE = false; + + /// ui width + static const UI_WIDTH = 375.0; + + /// ui width + static const UI_HEIGHT = 812.0; + +} diff --git a/lib/common/config/colorUtils.dart b/lib/common/config/colorUtils.dart new file mode 100644 index 0000000..adaef22 --- /dev/null +++ b/lib/common/config/colorUtils.dart @@ -0,0 +1,53 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-06 14:52:21 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-06 14:57:33 + * @FilePath: \marking_app\lib\utils\colorUtils.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'dart:ui'; +import 'dart:ui'; +import 'package:flutter/material.dart'; + +//调用的时候需要把hex改一下,比如#223344 needs change to 0xFF223344 +//即把#换成0xFF即可 + +MaterialColor createMaterialColor(Color color) { + List strengths = [.05]; + Map swatch = {}; + final int r = color.red, g = color.green, b = color.blue; + + for (int i = 1; i < 10; i++) { + strengths.add(0.1 * i); + } + for (var strength in strengths) { + final double ds = 0.5 - strength; + swatch[(strength * 1000).round()] = Color.fromRGBO( + r + ((ds < 0 ? r : (255 - r)) * ds).round(), + g + ((ds < 0 ? g : (255 - g)) * ds).round(), + b + ((ds < 0 ? b : (255 - b)) * ds).round(), + 1, + ); + } + return MaterialColor(color.value, swatch); +} + +class CommonColors { + static const Color defaultColor = Color.fromRGBO(45, 56, 76, 1); + + static Map map = Map.from({ + 'text_black': ColorItem( + title: 'text_black', color: const Color.fromRGBO(45, 56, 76, 1)), + }); + + ColorItem getColorItem(String key, {Color color = defaultColor}) { + return map[key] ?? ColorItem(color: color,title: 'default_color'); + } +} + +class ColorItem { + String title; + Color color; + ColorItem({required this.color, required this.title}); +} diff --git a/lib/common/const_text.dart b/lib/common/const_text.dart new file mode 100644 index 0000000..31a778b --- /dev/null +++ b/lib/common/const_text.dart @@ -0,0 +1,36 @@ +/*协议*/ +// ignore_for_file: constant_identifier_names +// ignore: camel_case_types +enum AGREEMENT_KEY { PRIVACY_GREEMENT, USER_AGREEMENT } + +// ignore: non_constant_identifier_names +final Map AGREEMENT_MAP = { + AGREEMENT_KEY.PRIVACY_GREEMENT: AgreementClass( + title: '隐私协议', + richText: '''

本软件尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、 + 更有个性化的服务,本软件会按照本隐私权政策的规定使用和披露您的个人信息。但本软件将以高度的勤勉、审慎义务对待这些信息。 + 除本隐私权政策另有规定外,在未征得您事先许可的情况下,本软件不会将这些信息对外披露或向第三方提供。本软件会不时更新本隐私权政策。 + 您在同意本软件服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本软件服务使用协议不可分割的一部分。 +

1.适用范围

a)在您使用本软件网络服务,本软件自动接收并记录的您的手机上的信息,包括但不限于您的健康数据、使用的语言、 + 访问日期和时间、软硬件特征信息及您需求的网页记录等数据;

2.信息的使用

a)在获得您的数据之后,本软件会将其上传至服务器, + 以生成您的排行榜数据,以便您能够更好地使用服务。

3.信息披露

a)本软件不会将您的信息披露给不受信任的第三方。 +

b)根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;

c)如您出现违反中国有关法律、 + 法规或者相关规则的情况,需要向第三方披露;

4.信息存储和交换

本软件收集的有关您的信息和资料将保存在本软件及(或)其关联公司的服务器上, + 这些信息和资料可能传送至您所在国家、地区或本软件收集信息和资料所在地的境外并在境外被访问、存储和展示。 +

5.信息安全

a)在使用本软件网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址。 + 请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,请您立即联络本软件客服,以便本软件采取相应措施。 +


''', + ), + AGREEMENT_KEY.USER_AGREEMENT: AgreementClass( + title: '用户协议', + richText: + '''

用户在使用技术开发方(即,以下统称“技术开发方”)提供的各项服务之前,应仔细阅读本《用户协议》(以下简称“本协议”)。用户一旦登录或使用技术开发方的服务,即视为用户已了解并明示同意本协议各项内容,本协议立即在用户与本技术开发方之间产生法律效力。用户登录、使用本产品服务的全部活动将受到本协议的约束并承担相应的责任和义务。如用户不同意本协议任何内容的,请用户立即停止使用技术开发方所提供的全部服务。 根据《中华人民共和国网络安全法》、《电信和互联网用户个人信息保护规定》及相关法律法规的规定,同时依据技术开发方与其合作伙伴之间的相关协议,用户必须已明示授权技术开发方合作伙伴(以下简称“合作伙伴”)、在此明示授权并委托技术开发方及其关联公司通过官方或相关实名认证平台、信用信息平台(包括但不限于:征信机构、银行信用信息平台、网络借贷平台、消费金融平台、第三方支付平台、公积金平台、投资理财平台等)及其它相关平台查询、验证、存储用户的个人信用信息,并输出给合作伙伴对用户的个人信用进行评估与参考使用。用户理解并同意,具体的授权查询、验证、存储及输出的内容以合作伙伴要求查询、验证、存储、输出以及技术开发方及其关联公司实际查询、验证、存储、输出的信息为准。技术开发方及其关联公司会在授权范围内对相关个人信息予以处理(包括但不限于为保护用户个人信息而加密处理、掩码处理等一切为实现相关协议目的而进行的所有必要处理)并仅提供给合作伙伴使用,但用户与合作伙伴之间因授权的有效性、授权内容、授权范围、授权期限等发生的争议纠纷与技术开发方无关。如用户对合作伙伴的上述授权事项有任何异议或争议的,应立即停止使用技术开发方所提供的全部服务。用户使用本服务的,即表明用户已明示对合作伙伴、技术开发方及其关联公司授权查询、验证、处理、存储、在约定范围内使用其个人信息,并对授权的效力、查询验证的内容、查询验证平台、处理方式、使用范围等相关事项无任何事实或法律上的异议或争议。 鉴于用户须授权合作伙伴并由该合作伙伴告知本服务后方能进入、登录并使用本服务,用户登录或使用本服务时起即视为用户与技术开发方的合作伙伴之间已存在合法的、充分的、必要的、不可撤销的授权,且用户已清楚知晓其授权提供相关信息可能对其造成的相关不利影响,如负面的信用评价等。为保护用户个人信息,技术开发方会采取合理措施对用户信息进行严格保密,同时督促并要求该特定合作伙伴进行严格保密。未经用户授权,技术开发方及其关联公司不会将用户信息提供给任何其他方。

一、协议主体

本协议是用户与技术开发方关于用户使用本服务所订立的协议。

二、关于本服务


    1. 本服务内容是指技术开发方通过本应用程序向其合作伙伴及用户提供的相关服务(简称“本服务”)。


    1. 对用户使用的本服务,技术开发方会不断丰富用户使用本服务的终端、形式等。


    1. 许可的范围:
      -(1)技术开发方授予用户一项个人的、不可转让及非排他性的许可,以使用本应用程序。
      -(2)本条及本协议其他条款未明示授权的其他一切知识产权权利仍由技术开发方保留。技术开发方如果未行使前述任何权利,并不构成对该权利的放弃。

三、账号登录

为使用本应用程序用户可能需要输入个人信息进行登录与使用。 用户清楚知晓,其向技术开发方提供的账户仅限本人使用,否则,用户可能会对用户或他人造成侵权。用户承诺并同意,使用同一设备、同一身份证号或账号使用本协议项下服务的,均视为用户本人的行为。用户应妥善保管自身设备、身份证件及账号密码信息,审慎交由他人使用或使用他人设备、身份证件或账户信息,如用户违反本约定给用户或他人造成损失的,技术开发方不应也不会承担任何法律责任。用户若因此给技术开发方造成损失的,应承担技术开发方所遭受的全部损失。

四、应用程序的使用

如果用户从非技术开发方合作伙伴的应用程序或非技术开发方合作伙伴处获取本应用程序或与本应用程序名称相同的安装程序,技术开发方无法保证该应用程序能够正常使用,并对因此给用户造成的损失不予负责。

五、应用程序的更新

  1. 为了增进用户体验、完善服务内容,技术开发方将不断努力为用户时时提供应用程序更新(这些更新可能会采取应用程序替换、修改、功能强化、版本升级等形式)。

  2. 为了改善用户体验,并保证服务的安全性和功能的一致性,技术开发方有权不经向用户特别通知而对应用程序进行更新,或者对应用程序的部分功能效果进行改变或限制。

六、用户个人信息保护


    1. 保护用户个人信息是技术开发方的一项基本原则,技术开发方将会采取合理的措施保护用户的个人信息。除法律法规规定及用户授权的情形外,未经用户许可技术开发方不会向任何第三方公开、透露用户个人信息。


    1. 用户在登录账号或使用本服务的过程中,可能需要填写一些必要的信息。若用户填写的信息不真实或不完整,则可能无法正常使用本服务。


    1. 一般情况下,用户可随时浏览、修改自己提交的信息,但出于安全性和身份识别的考虑,用户可能无法修改注册时提供的初始注册信息及其他验证信息。


    1. 技术开发方将运用各种安全技术和程序建立完善的管理制度来保护用户的个人信息,以免遭受未经授权的访问、使用或披露。

七、授权事项及行为规范


    1. 授权事项
      -(1)用户充分理解并同意:用户在使用本服务时,可能需要使用用户终端设备的相关权限、接口及相关设备信息等才能实现相应的功能。
      -(2)用户可以选择不向技术开发方提供用户的某些信息,但因此可能会导致相关服务功能无法实现。
      -(3)为实现本协议目的为合作伙伴及用户提供更加优质、安全的服务,用户同意并明示授权技术开发方及其关联公司对用户的相关个人信息进行查询、验证、存储、处理并在约定范围内使用(提供给用户已授权的合作伙伴对用户进行信用评估及参考使用)。技术开发方及其关联公司对用户的个人信息进行严格保密。本协议项下的授权为不可撤销的授权。
      -(4)用户知晓并明示授权同意技术开发方及其关联公司依据相关法律法规的规定,受合作伙伴委托向第三方征信机构或数据机构等合法查询、验证、审核用户信息,上述信息包括但不限于个人基本信息、特征信息(包括但不限于用户的法院失信信息、网络失信信息、是否为羊毛党信息、是否曾使用通讯小号及可疑设备信息等)、关联信息(即用户的身份证信息、手机号、手机设备及银行卡之间的关联关系,以判断用户信息是否有异常,该关联关系不涉及具体的个人敏感信息)、借贷交易信息、网络投资理财信息、公积金信息、公用事业信息、央行征信报告、个人网络数据信息等合作伙伴需要验证或参考使用的相关用户信息。技术开发方具体查询、验证及审核的信息最终以合作伙伴需要验证、需要参考使用及实际验证与使用的信息为准。技术开发方对所获取的信息,仅在用户与合作伙伴之间有关个人信用信息评估等合作伙伴业务相关工作中使用。技术开发方及其关联公司将对所获取的信息向该合作伙伴进行提供,除此之外,未经用户授权,技术开发方及其关联公司不得也不会向其他机构或个人泄露、披露或提供用户的信息


    1. 用户禁止行为除非法律允许或技术开发方书面许可,用户不得从事下列行为:
      -(1)删除本应用程序及其副本上关于著作权的信息。
      -(2)对本应用程序进行反向工程、反向汇编、反向编译,或者以其他方式尝试发现本应用程序的源代码。
      -(3)对技术开发方拥有知识产权的内容进行使用、出租、出借、复制、修改、链接、转载、汇编、发表、出版等。
      -(4)通过修改或伪造应用程序运行中的指令、数据,增加、删减、变动应用程序的功能或运行效果,或者将用于上述用途的应用程序、方法进行运营或向公众传播,无论这些行为是否为商业目的。
      -(5)自行、授权他人或利用第三方应用程序对本应用程序及其组件、模块、数据等进行干扰。
      -(6)其他未经技术开发方明示授权的行为。

  1. 对自己行为负责用户充分了解并同意,用户必须为自己对合作伙伴的授权(包括但不限于授权方式、授权内容及授权期限等)以及其账户下的相关行为负责。技术开发方会督促合作伙伴获取用户的授权后方能对相关信息进行查询、验证或使用并要求合作伙伴对用户的信息进行严格保密,但用户应对使用本服务时接触到的内容自行加以判断,如对授权相关事项及信息安全有任何异议或争议的,应立即停止使用本服务。技术开发方无法且不会对用户与合作伙伴之间的任何争议或纠纷而承担责任,用户未按约定要求立即停止使用本服务的,技术开发方对非因技术开发方的原因而产生的任何风险或损失将不承担任何责任。

八、知识产权声明


    1. 技术开发方是本应用程序的知识产权权利人。本应用程序的著作权、商标权、专利权、商业秘密等知识产权,以及与本应用程序相关的所有信息内容(包括但不限于文字、图片、音频、视频、图表、界面设计、版面框架、有关数据或电子文档等)均受中华人民共和国法律法规和相应的国际条约保护,技术开发方依法享有上述相关知识产权,但相关权利人依照法律规定应享有的权利除外。


    1. 未经技术开发方或相关权利人书面同意,用户不得为任何商业或非商业目的自行或许可任何第三方实施、利用、转让上述知识产权。

九、终端安全责任


    1. 用户理解并同意,本应用程序或本服务同大多数互联网应用程序、服务一样,可能会受多种因素影响(包括但不限于用户原因、网络服务质量、社会环境等);也可能会受各种安全问题的侵扰(包括但不限于他人非法利用用户资料,进行现实中的骚扰;用户下载安装的其他应用程序或访问的其他网站中可能含有病毒、木马程序或其他恶意程序,威胁用户终端的信息和数据的安全,继而影响本应用程序、本服务的正常使用等)。因此,用户应加强信息安全及个人信息的保护意识,注意密码保护,以免遭受损失。出现上述情况时技术开发方将努力在第一时间与相关方配合,及时进行修复,但是由此给用户造成的损失技术开发方在法律允许的范围内免责。


    1. 用户不得制作、发布、使用、传播用于窃取技术开发方账号及他人个人信息、财产的恶意程序。


    1. 维护应用程序安全与正常使用是技术开发方和用户的共同责任,技术开发方将按照行业标准合理审慎地采取必要技术措施保护用户的终端信息和数据安全。


    1. 在法律允许的范围内,技术开发方对以下情形导致的服务中断或受阻不承担责任:
      -(1)受到计算机病毒、木马或其他恶意程序、黑客攻击的破坏。
      -(2)用户或技术开发方的电脑软件、系统、硬件和通信线路出现故障。
      -(3)用户操作不当。
      -(4)用户通过非技术开发方授权的方式使用本服务。
      -(5)其他技术开发方无法控制或合理预见的情形。

十、不可抗力及合理免责

“不可抗力”是指在本协议签订后发生的、受影响一方无法预见、无法避免并无法克服的客观情况。此等事件包括但不限于水灾、火灾、旱灾、台风、地震及其它自然灾害、罢工、骚动、暴乱及战争以及政府部门的作为或不作为、法律法规或政策调整、数据来源变更(包括但不限于其服务内容及形式的变更)、国内数据渠道瘫痪、黑客攻击、计算机病毒侵入、新型病毒爆发、因电信运营商问题导致网络中断服务器不可访问、停电、系统故障、传输线路、通信故障等技术开发方无法控制的因素。因受不可抗力影响而不能履行或不能完全履行本协议的不视为违约,不应承担相应违约责任 。

十一、其他


    1. 用户使用本应用程序或本服务即视为用户已阅读并同意受本协议的约束。技术开发方有权在必要时修改本协议条款。用户可以在本应用程序、本服务的最新版本中查阅相关协议条款。本协议条款变更后,如果用户继续登录、使用本应用程序、本服务,即视为用户已接受修改后的协议。如果用户不接受修改后的协议,应当停止使用本应用程序。


    1. 本协议的成立、生效、履行、解释及纠纷解决,适用中华人民共和国大陆地区法律(不包括冲突法)。


    1. 若用户和技术开发方之间发生任何纠纷或争议,首先应友好协商解决;协商不成的,用户同意将纠纷或争议提交被告方所在地人民法院管辖。


    1. 本协议所有条款的标题仅为阅读方便,本身并无实际涵义,不能作为本协议涵义解释的依据。5. 本协议条款无论因何种原因部分无效或不可执行,其余条款仍有效,对双方具有约束力。




''', + ) +}; + +/* TYPE */ +class AgreementClass { + String title; + String richText; + AgreementClass({required this.title, required this.richText}); +} diff --git a/lib/common/job/common/base_page.dart b/lib/common/job/common/base_page.dart new file mode 100644 index 0000000..375cd1a --- /dev/null +++ b/lib/common/job/common/base_page.dart @@ -0,0 +1,31 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-19 16:17:38 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-19 16:22:41 + * @FilePath: \marking_app\lib\common\model\common\base_page.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; + +part 'base_page.g.dart'; + + +@JsonSerializable() + class BasePage extends Object { + + @JsonKey(name: 'Page') + int page; + + @JsonKey(name: 'Limit') + int limit; + + BasePage(this.page,this.limit,); + + factory BasePage.fromJson(Map srcJson) => _$BasePageFromJson(srcJson); + + Map toJson() => _$BasePageToJson(this); + +} + + diff --git a/lib/common/job/common/base_page.g.dart b/lib/common/job/common/base_page.g.dart new file mode 100644 index 0000000..7169c8d --- /dev/null +++ b/lib/common/job/common/base_page.g.dart @@ -0,0 +1,17 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_page.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BasePage _$BasePageFromJson(Map json) => BasePage( + json['Page'] as int, + json['Limit'] as int, + ); + +Map _$BasePageToJson(BasePage instance) => { + 'Page': instance.page, + 'Limit': instance.limit, + }; diff --git a/lib/common/job/common/base_page_data.dart b/lib/common/job/common/base_page_data.dart new file mode 100644 index 0000000..3fde8be --- /dev/null +++ b/lib/common/job/common/base_page_data.dart @@ -0,0 +1,29 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-18 17:44:15 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-19 16:19:15 + * @FilePath: \marking_app\lib\common\model\common\base_page.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; + +part 'base_page_data.g.dart'; + +@JsonSerializable(genericArgumentFactories: true, fieldRename: FieldRename.snake) + class BasePageData extends Object { + + @JsonKey(name: 'items') + List items; + + @JsonKey(name: 'total') + int total; + + BasePageData(this.items,this.total,); + + + factory BasePageData.fromJson( Map json, T Function(dynamic json) fromJsonT) => _$BasePageDataFromJson(json, fromJsonT); + Map toJson(Object Function(T value) toJsonT) => _$BasePageDataToJson(this, toJsonT); +} + + diff --git a/lib/common/job/common/base_page_data.g.dart b/lib/common/job/common/base_page_data.g.dart new file mode 100644 index 0000000..6f6a5c6 --- /dev/null +++ b/lib/common/job/common/base_page_data.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_page_data.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BasePageData _$BasePageDataFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + BasePageData( + (json['items'] as List).map(fromJsonT).toList(), + json['total'] as int, + ); + +Map _$BasePageDataToJson( + BasePageData instance, + Object? Function(T value) toJsonT, +) => + { + 'items': instance.items.map(toJsonT).toList(), + 'total': instance.total, + }; diff --git a/lib/common/job/common/base_page_data_report.dart b/lib/common/job/common/base_page_data_report.dart new file mode 100644 index 0000000..69177b6 --- /dev/null +++ b/lib/common/job/common/base_page_data_report.dart @@ -0,0 +1,19 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'base_page_data_report.g.dart'; + + +@JsonSerializable(genericArgumentFactories: true, fieldRename: FieldRename.snake) + class BasePageDataReport extends Object { + + @JsonKey(name: 'Data') + List items; + + @JsonKey(name: 'Total') + int total; + + BasePageDataReport(this.items,this.total,); + + factory BasePageDataReport.fromJson( Map json, T Function(dynamic json) fromJsonT) => _$BasePageDataReportFromJson(json, fromJsonT); + Map toJson(Object Function(T value) toJsonT) => _$BasePageDataReportToJson(this, toJsonT); +} \ No newline at end of file diff --git a/lib/common/job/common/base_page_data_report.g.dart b/lib/common/job/common/base_page_data_report.g.dart new file mode 100644 index 0000000..74206d4 --- /dev/null +++ b/lib/common/job/common/base_page_data_report.g.dart @@ -0,0 +1,25 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_page_data_report.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BasePageDataReport _$BasePageDataReportFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + BasePageDataReport( + (json['Data'] as List).map(fromJsonT).toList(), + json['Total'] as int, + ); + +Map _$BasePageDataReportToJson( + BasePageDataReport instance, + Object? Function(T value) toJsonT, +) => + { + 'Data': instance.items.map(toJsonT).toList(), + 'Total': instance.total, + }; diff --git a/lib/common/job/common/base_page_report.dart b/lib/common/job/common/base_page_report.dart new file mode 100644 index 0000000..ca139cf --- /dev/null +++ b/lib/common/job/common/base_page_report.dart @@ -0,0 +1,31 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-19 16:17:38 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-19 16:22:41 + * @FilePath: \marking_app\lib\common\model\common\base_page.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; + +part 'base_page_report.g.dart'; + + +@JsonSerializable() + class BasePageReport extends Object { + + @JsonKey(name: 'PageIndex') + int page; + + @JsonKey(name: 'PageSize') + int limit; + + BasePageReport(this.page,this.limit,); + + factory BasePageReport.fromJson(Map srcJson) => _$BasePageReportFromJson(srcJson); + + Map toJson() => _$BasePageReportToJson(this); + +} + + diff --git a/lib/common/job/common/base_page_report.g.dart b/lib/common/job/common/base_page_report.g.dart new file mode 100644 index 0000000..524ffcd --- /dev/null +++ b/lib/common/job/common/base_page_report.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_page_report.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BasePageReport _$BasePageReportFromJson(Map json) => + BasePageReport( + json['PageIndex'] as int, + json['PageSize'] as int, + ); + +Map _$BasePageReportToJson(BasePageReport instance) => + { + 'PageIndex': instance.page, + 'PageSize': instance.limit, + }; diff --git a/lib/common/job/common/base_structure_result.dart b/lib/common/job/common/base_structure_result.dart new file mode 100644 index 0000000..0518311 --- /dev/null +++ b/lib/common/job/common/base_structure_result.dart @@ -0,0 +1,38 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 18:30:11 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-14 10:20:21 + * @FilePath: \marking_app\lib\common\model\common\base_structure_result.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; +import 'package:school_asignment_app/common/request/request_config.dart'; + +part 'base_structure_result.g.dart'; + +@JsonSerializable(genericArgumentFactories: true, fieldRename: FieldRename.snake) +class BaseStructureResult extends Object { + @JsonKey(name: 'success') + bool success; + + @JsonKey(name: 'code') + int code; + + @JsonKey(name: 'message') + String? message; + + @JsonKey(name: 'data') + T? data; + + BaseStructureResult( + this.code, + this.message, + this.data, { + this.success = false, + }) { + success = (code == RequestConfig.successCode); + } + factory BaseStructureResult.fromJson(Map json, T Function(dynamic json) fromJsonT) => _$BaseStructureResultFromJson(json, fromJsonT); + Map toJson(Object Function(T value) toJsonT) => _$BaseStructureResultToJson(this, toJsonT); +} diff --git a/lib/common/job/common/base_structure_result.g.dart b/lib/common/job/common/base_structure_result.g.dart new file mode 100644 index 0000000..0398e4c --- /dev/null +++ b/lib/common/job/common/base_structure_result.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_structure_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BaseStructureResult _$BaseStructureResultFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + BaseStructureResult( + json['code'] as int, + json['message'] as String?, + _$nullableGenericFromJson(json['data'], fromJsonT), + success: json['success'] as bool? ?? false, + ); + +Map _$BaseStructureResultToJson( + BaseStructureResult instance, + Object? Function(T value) toJsonT, +) => + { + 'success': instance.success, + 'code': instance.code, + 'message': instance.message, + 'data': _$nullableGenericToJson(instance.data, toJsonT), + }; + +T? _$nullableGenericFromJson( + Object? input, + T Function(Object? json) fromJson, +) => + input == null ? null : fromJson(input); + +Object? _$nullableGenericToJson( + T? input, + Object? Function(T value) toJson, +) => + input == null ? null : toJson(input); diff --git a/lib/common/job/common/base_structure_result_report.dart b/lib/common/job/common/base_structure_result_report.dart new file mode 100644 index 0000000..008eac6 --- /dev/null +++ b/lib/common/job/common/base_structure_result_report.dart @@ -0,0 +1,38 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 18:30:11 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-14 10:20:21 + * @FilePath: \marking_app\lib\common\model\common\base_structure_result.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; +import 'package:school_asignment_app/common/request/request_config.dart'; + +part 'base_structure_result_report.g.dart'; + +@JsonSerializable(genericArgumentFactories: true, fieldRename: FieldRename.snake) +class BaseStructureResultReport extends Object { + @JsonKey(name: 'success') + bool success; + + @JsonKey(name: 'Code') + int code; + + @JsonKey(name: 'Message') + String? message; + + @JsonKey(name: 'Data') + T? data; + + BaseStructureResultReport( + this.code, + this.message, + this.data, { + this.success = false, + }) { + success = (code == RequestConfig.successCode); + } + factory BaseStructureResultReport.fromJson(Map json, T Function(dynamic json) fromJsonT) => _$BaseStructureResultReportFromJson(json, fromJsonT); + Map toJson(Object Function(T value) toJsonT) => _$BaseStructureResultReportToJson(this, toJsonT); +} diff --git a/lib/common/job/common/base_structure_result_report.g.dart b/lib/common/job/common/base_structure_result_report.g.dart new file mode 100644 index 0000000..00e7b5b --- /dev/null +++ b/lib/common/job/common/base_structure_result_report.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'base_structure_result_report.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +BaseStructureResultReport _$BaseStructureResultReportFromJson( + Map json, + T Function(Object? json) fromJsonT, +) => + BaseStructureResultReport( + json['Code'] as int, + json['Message'] as String?, + _$nullableGenericFromJson(json['Data'], fromJsonT), + success: json['success'] as bool? ?? false, + ); + +Map _$BaseStructureResultReportToJson( + BaseStructureResultReport instance, + Object? Function(T value) toJsonT, +) => + { + 'success': instance.success, + 'Code': instance.code, + 'Message': instance.message, + 'Data': _$nullableGenericToJson(instance.data, toJsonT), + }; + +T? _$nullableGenericFromJson( + Object? input, + T Function(Object? json) fromJson, +) => + input == null ? null : fromJson(input); + +Object? _$nullableGenericToJson( + T? input, + Object? Function(T value) toJson, +) => + input == null ? null : toJson(input); diff --git a/lib/common/job/common/upload_img_secret_key.dart b/lib/common/job/common/upload_img_secret_key.dart new file mode 100644 index 0000000..19465ec --- /dev/null +++ b/lib/common/job/common/upload_img_secret_key.dart @@ -0,0 +1,57 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'upload_img_secret_key.g.dart'; + + +@JsonSerializable() + class UploadImgSecretKey extends Object { + + @JsonKey(name: 'account') + String? account; + + @JsonKey(name: 'bucketName') + String? bucketName; + + @JsonKey(name: 'endPoint') + int? endPoint; + + @JsonKey(name: 'ip') + String? ip; + + @JsonKey(name: 'password') + String? password; + + @JsonKey(name: 'imgSecretKey') + bool? imgSecretKey; + + // 是否打开工具 + bool annotationSwitch; + + UploadImgSecretKey({this.account,this.bucketName,this.endPoint,this.ip,this.password,this.imgSecretKey,this.annotationSwitch = false}); + + factory UploadImgSecretKey.fromJson(Map srcJson) => _$UploadImgSecretKeyFromJson(srcJson); + + Map toJson() => _$UploadImgSecretKeyToJson(this); + +} + + +/// 返回结果文件实体类 +@JsonSerializable() +class FileResult extends Object{ + String? path; // 本地相对地址 + String? url; // 图片上传返回url地址 + dynamic? otherParam; + String myObject; // 我的项目名称 + bool success; // 是否成功 + + + FileResult({required this.myObject, this.url, this.success = false,this.otherParam}); + + + + factory FileResult.fromJson(Map srcJson) => _$FileResultFromJson(srcJson); + + Map toJson() => _$FileResultToJson(this); +} + diff --git a/lib/common/job/common/upload_img_secret_key.g.dart b/lib/common/job/common/upload_img_secret_key.g.dart new file mode 100644 index 0000000..04211a5 --- /dev/null +++ b/lib/common/job/common/upload_img_secret_key.g.dart @@ -0,0 +1,45 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'upload_img_secret_key.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UploadImgSecretKey _$UploadImgSecretKeyFromJson(Map json) => + UploadImgSecretKey( + account: json['account'] as String?, + bucketName: json['bucketName'] as String?, + endPoint: json['endPoint'] as int?, + ip: json['ip'] as String?, + password: json['password'] as String?, + imgSecretKey: json['imgSecretKey'] as bool?, + annotationSwitch: json['annotationSwitch'] as bool? ?? false, + ); + +Map _$UploadImgSecretKeyToJson(UploadImgSecretKey instance) => + { + 'account': instance.account, + 'bucketName': instance.bucketName, + 'endPoint': instance.endPoint, + 'ip': instance.ip, + 'password': instance.password, + 'imgSecretKey': instance.imgSecretKey, + 'annotationSwitch': instance.annotationSwitch, + }; + +FileResult _$FileResultFromJson(Map json) => FileResult( + myObject: json['myObject'] as String, + url: json['url'] as String?, + success: json['success'] as bool? ?? false, + otherParam: json['otherParam'], + )..path = json['path'] as String?; + +Map _$FileResultToJson(FileResult instance) => + { + 'path': instance.path, + 'url': instance.url, + 'otherParam': instance.otherParam, + 'myObject': instance.myObject, + 'success': instance.success, + }; diff --git a/lib/common/job/user_info.dart b/lib/common/job/user_info.dart new file mode 100644 index 0000000..db345cd --- /dev/null +++ b/lib/common/job/user_info.dart @@ -0,0 +1,53 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-14 10:44:46 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-19 20:17:48 + * @FilePath: \marking_app\lib\common\model\user\user_info.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'dart:convert'; + +import 'package:json_annotation/json_annotation.dart'; + +part 'user_info.g.dart'; + + +@JsonSerializable(checked: true) + class UserInfo extends Object { + + @JsonKey(name: 'id') + String id =''; + + @JsonKey(name: 'userName') + String userName = ''; + + @JsonKey(name: 'loginName') + String loginName = ''; + + @JsonKey(name: 'subjectIds') + List subjectIds = []; + + @JsonKey(name: 'schoolId') + int schoolId = 0; + + @JsonKey(name: 'schoolName') + String schoolName = ''; + + + @JsonKey(name: 'avatar') + String avatar =''; + + @JsonKey(name: 'positionNames') + List positionNames=[]; + + + UserInfo(); + + factory UserInfo.fromJson(Map srcJson) => _$UserInfoFromJson(srcJson); + + Map toJson() => _$UserInfoToJson(this); + +} + + diff --git a/lib/common/job/user_info.g.dart b/lib/common/job/user_info.g.dart new file mode 100644 index 0000000..a0a5342 --- /dev/null +++ b/lib/common/job/user_info.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_info.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserInfo _$UserInfoFromJson(Map json) => $checkedCreate( + 'UserInfo', + json, + ($checkedConvert) { + final val = UserInfo(); + $checkedConvert('id', (v) => val.id = v as String); + $checkedConvert('userName', (v) => val.userName = v as String); + $checkedConvert('loginName', (v) => val.loginName = v as String); + $checkedConvert( + 'subjectIds', + (v) => val.subjectIds = + (v as List).map((e) => e as int).toList()); + $checkedConvert('schoolId', (v) => val.schoolId = v as int); + $checkedConvert('schoolName', (v) => val.schoolName = v as String); + $checkedConvert('avatar', (v) => val.avatar = v as String); + $checkedConvert( + 'positionNames', + (v) => val.positionNames = + (v as List).map((e) => e as String).toList()); + return val; + }, + ); + +Map _$UserInfoToJson(UserInfo instance) => { + 'id': instance.id, + 'userName': instance.userName, + 'loginName': instance.loginName, + 'subjectIds': instance.subjectIds, + 'schoolId': instance.schoolId, + 'schoolName': instance.schoolName, + 'avatar': instance.avatar, + 'positionNames': instance.positionNames, + }; diff --git a/lib/common/job/user_login.dart b/lib/common/job/user_login.dart new file mode 100644 index 0000000..7e60083 --- /dev/null +++ b/lib/common/job/user_login.dart @@ -0,0 +1,32 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 14:50:51 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-13 17:22:16 + * @FilePath: \marking_app\lib\common\model\UserLogin.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:json_annotation/json_annotation.dart'; + +part 'user_login.g.dart'; + + +@JsonSerializable(checked: true) + class UserLogin extends Object { + + @JsonKey(name: 'access_token') + String accessToken; + + @JsonKey(name: 'expires_in') + int expiresIn; + + @JsonKey(name: 'token_type') + String tokenType; + + UserLogin(this.accessToken,this.expiresIn,this.tokenType,); + + factory UserLogin.fromJson(Map srcJson) => _$UserLoginFromJson(srcJson); + + Map toJson() => _$UserLoginToJson(this); + +} \ No newline at end of file diff --git a/lib/common/job/user_login.g.dart b/lib/common/job/user_login.g.dart new file mode 100644 index 0000000..b0b137a --- /dev/null +++ b/lib/common/job/user_login.g.dart @@ -0,0 +1,31 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'user_login.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +UserLogin _$UserLoginFromJson(Map json) => $checkedCreate( + 'UserLogin', + json, + ($checkedConvert) { + final val = UserLogin( + $checkedConvert('access_token', (v) => v as String), + $checkedConvert('expires_in', (v) => v as int), + $checkedConvert('token_type', (v) => v as String), + ); + return val; + }, + fieldKeyMap: const { + 'accessToken': 'access_token', + 'expiresIn': 'expires_in', + 'tokenType': 'token_type' + }, + ); + +Map _$UserLoginToJson(UserLogin instance) => { + 'access_token': instance.accessToken, + 'expires_in': instance.expiresIn, + 'token_type': instance.tokenType, + }; diff --git a/lib/common/request/request_config.dart b/lib/common/request/request_config.dart new file mode 100644 index 0000000..748c652 --- /dev/null +++ b/lib/common/request/request_config.dart @@ -0,0 +1,80 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 11:28:23 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-09-14 11:17:20 + * @FilePath: \marking_app\lib\config\RequestConfig.dart + * @Description: 请求工具类 + */ +import 'package:school_asignment_app/common/job/common/base_page.dart'; + +class RequestConfig { + /* 测试地址 + static const devBaseUrl = "http://192.168.2.9:6600"; // 测试环境 ==> 基本请求接口 + // static const devBaseUrl = "http://192.168.2.8:6700"; // 测试环境 ==> 基本请求接口 + static const devLoginBaseUrl = "http://192.168.2.9:6400"; // 基本请求接口 + static const devBaseUrlOfReport = "http://192.168.2.9:4000"; // 获取报告接口*/ + + static const devBaseUrl = "https://mk-hw.23544.com"; // 基本请求 + static const devLoginBaseUrl = "https://mk-hw.23544.com"; // 登录接口 + static const devBaseUrlOfReport = "https://mhw.qwit.top"; // 获取报告接口 + static const proBaseUrlOfHomework = "https://mk-hw.23544.com/hw"; // 获取作业接口 + + /* 正式地址 */ + static const proBaseUrl = "https://mk-hw.23544.com"; // 基本请求 + static const proLoginBaseUrl = "https://mk-hw.23544.com"; // 登录接口 + static const proBaseUrlOfReport = "https://dc-api.23544.com"; // 获取报告接口 + // static const proBaseUrlOfHomework = "https://mk-hw.23544.com/hw"; // 获取作业接口 + + static const hwProxyKeywords = "/hw"; // 作业代理条件关键字 + + // https://mk-api.23544.com/hw/hw/api/Task/answer + // http://192.168.2.9:6400/hw/api/Task/answer + + static RequestConfig? _instance; + String baseUrl; + String loginBaseUrl; + String baseUrlOfReport; + + static const connectTimeout = 8000; // 连接超时 + static const receiveTimeout = 8000; // 接收超时 + + static const bool requestDataPrinting = true; // 打印返回数据 + static const bool printSwitch = true; // 打印返回数据 + + static const successCode = 200; // 返回成功code + static final BasePage basePage = BasePage(1, 10); // 分页参数 + + // 私有化构造函数,防止外部直接实例化 +// 私有化构造函数,防止外部直接实例化 + RequestConfig._( + {required this.baseUrl, + required this.baseUrlOfReport, + required this.loginBaseUrl}); + + factory RequestConfig() { + if (_instance == null) { + late String newBaseUrl; + late String newBaseUrlOfReport; + late String newLoginBaseUrl; + + if (bool.fromEnvironment('dart.vm.product')) { + // 正式环境下的代码 + + newLoginBaseUrl = proLoginBaseUrl; + newBaseUrl = proBaseUrl; + newBaseUrlOfReport = proBaseUrlOfReport; + } else { + // 在生产环境下执行的代码 + newBaseUrl = devBaseUrl; + newBaseUrlOfReport = devBaseUrlOfReport; + newLoginBaseUrl = devLoginBaseUrl; + } + _instance = RequestConfig._( + baseUrl: newBaseUrl, + baseUrlOfReport: newBaseUrlOfReport, + loginBaseUrl: newLoginBaseUrl); + } + return _instance!; + } +} diff --git a/lib/common/request/rest_dio.dart b/lib/common/request/rest_dio.dart new file mode 100644 index 0000000..c8fceb0 --- /dev/null +++ b/lib/common/request/rest_dio.dart @@ -0,0 +1,427 @@ +import 'dart:io'; +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:dio/dio.dart'; +import 'package:dio/adapter.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:package_info/package_info.dart'; +import 'package:school_asignment_app/common/request/request_config.dart'; +import 'package:school_asignment_app/common/store/app_storage_key.dart'; +import 'package:school_asignment_app/common/the_global.dart'; +import 'package:school_asignment_app/common/utils/storage.dart'; +import 'package:school_asignment_app/common/utils/toast_utils.dart'; + +class RestDio { + late Dio _dio; + // 单例模式 + static final RestDio instance = RestDio._internal(); + factory RestDio() => instance; + RestDio._internal() { + init(); + } + + // 初始化请求配置 + init() { + BaseOptions options = BaseOptions( + baseUrl: RequestConfig().baseUrl, + connectTimeout: RequestConfig.connectTimeout, + receiveTimeout: RequestConfig.receiveTimeout, + ); + _dio = Dio(options); + _dio.interceptors.add(AuthInterceptor()); // 添加 token + _dio.interceptors.add(ResponseHandle()); // 添加 数据返回拦截 + _dio.interceptors.add(TheError()); // 添加 数据返回拦截 + const isProd = bool.fromEnvironment('dart.vm.product'); + if (!isProd && RequestConfig.requestDataPrinting) { + _dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); //添加日志 + } + // 添加https证书 + setHttpsPEM(); + // setHttpsPKCS12(); + + // 使用代理 + // setFindProxy(); + } + /// restful post 表单提交操作 + Future get(String path, {Map? queryParameters, Options? options}) async { + Options requestOptions = options ?? Options(); + var response = await _dio.get( + path, + queryParameters: queryParameters, + options: requestOptions, + cancelToken: CancelToken(), + ); + return response.data; + } + + + /// restful post 表单提交操作 + Future post(String path, {Map? data, Options? options}) async { + Options requestOptions = options ?? Options(); + var response = await _dio.post( + path, + data: data, + options: requestOptions, + cancelToken: CancelToken(), + ); + return response.data; + } + + String PEM = "XXXXX"; // certificate content + String PKCS12File = "XXXXX"; // certificate content + + //dio 基本方法 + Future getDio() async { + return _dio; + } + + //添加证书 + setHttpsPEM() async { + (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { + client.badCertificateCallback = (X509Certificate cert, String host, int port) { + // if (cert.pem == PEM) { + // // Verify the certificate + // return true; + // } + // return false; + return true; + }; + }; + } + + setHttpsPKCS12() async { + (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { + SecurityContext sc = new SecurityContext(); + //file is the path of certificate + sc.setTrustedCertificates(PKCS12File); + HttpClient httpClient = new HttpClient(context: sc); + return httpClient; + }; + } + + //设置代理 + setFindProxy() async { + // 设置请求拦截器 + _dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) { + // 判断 URI 的路径是否包含指定字符串 + if (options.uri.path.contains(RequestConfig.hwProxyKeywords)) { + // 设置代理地址 + _dio.httpClientAdapter = DefaultHttpClientAdapter(); + (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { + client.findProxy = (uri) { + print('进入开始代理...............'); + return RequestConfig.proBaseUrlOfHomework; + }; + }; + } + + return handler.next(options); // 继续发送请求 + })); + } +} + +/* +* +*AuthInterceptor +*添加header认证 +* */ +class AuthInterceptor extends Interceptor { + String PLATFORM = "android"; //可根据代码进行判断 + + @override + onRequest(RequestOptions options, RequestInterceptorHandler handler) async { + //获取app版本 + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + + String version = packageInfo.version; + if (Platform.isIOS) { + PLATFORM = "ios"; + } else if (Platform.isAndroid) { + PLATFORM = "android"; + } else if (Platform.isWindows) { + PLATFORM = "Windows"; + } else if (Platform.isMacOS) { + PLATFORM = "macos"; + } else if (Platform.isLinux) { + PLATFORM = "Linux"; + } + + Map headers = {}; + headers["Accept-Charset"] = "utf-8"; + headers["Connection"] = "keep-alive"; + headers["Accept"] = "*/*"; + headers["x-version"] = version; //自己更改配置 + headers["x-platform"] = PLATFORM; + //获取存储数据 保存header token + String? token = StorageService.to.read(AppStorageKey.STORAGE_USER_TOKEN); + + if (null != token && token.isNotEmpty) { + headers["Authorization"] = 'Bearer $token'; //添加自己项目中的请求头 进行保存 + } + + options.headers = headers; + Uri uri = options.uri; + print(uri.toString()); + // 判断请求的 URL 是否包含指定字符串 + if (uri.toString().contains(RequestConfig.hwProxyKeywords)) { + String newPath = options.path.replaceFirst(RegExp('^${RequestConfig.hwProxyKeywords}'), ''); + options.path = newPath; + // 修改请求的 URL + options.baseUrl = RequestConfig.proBaseUrlOfHomework; + } + + // print('请求参数query:' + jsonEncode(options.queryParameters)); + // print('请求参数data:' + jsonEncode(options.data)); + + return super.onRequest(options, handler); + } +} + +/* + * ResponseHandle + * 监听返回响应 + **/ +class ResponseHandle extends Interceptor { + @override + void onResponse(Response response, ResponseInterceptorHandler handler) { + const isProd = bool.fromEnvironment('dart.vm.product'); + if (!isProd && RequestConfig.requestDataPrinting) { + // printJson(response.data); + } + super.onResponse(response, handler); + } +} + +/* + * ResponseHandle + * 监听返回响应 + **/ +class TheError extends Interceptor { + // 是否有网 + Future isConnected() async { + var connectivityResult = await (Connectivity().checkConnectivity()); + return connectivityResult != ConnectivityResult.none; + } + + @override + Future onError(DioError err, ErrorInterceptorHandler handler) async { + // 自定义一个socket实例,因为dio原生的实例,message属于是只读的 + // 这里是我单独加的,因为默认的dio err实例,的几种类型,缺少无网络情况下的错误提示信息 + if (err.error is SocketException) { + err.error = MyDioSocketException( + err.message.contains('111') ? "服务器拒绝连接,请重试" : err.message, + osError: err.error?.osError, + address: err.error?.address, + port: err.error?.port, + ); + } + // dio默认的错误实例,如果是没有网络,只能得到一个未知错误,无法精准的得知是否是无网络的情况 + if (err.type == DioErrorType.other) { + bool isConnectNetWork = await isConnected(); + if (!isConnectNetWork && err.error is MyDioSocketException) { + err.error.message = "当前网络不可用,请检查您的网络"; + } + } + + // error统一处理 + AppException appException = AppException.create(err); + + // 错误提示 + // debugPrint('DioError===: ${appException.toString()}'); + err = appException; + + return super.onError(err, handler); + } +} + +String getDioErrorTypeStr(DioError err) { + DioErrorType errorType = err.type; + String str; + switch (errorType) { + case DioErrorType.connectTimeout: + str = '连接超时,请检查网络再重试'; + break; + case DioErrorType.sendTimeout: + str = '发送时间超时,请重试'; + break; + case DioErrorType.receiveTimeout: + str = '接收数据超时,请重试'; + break; + case DioErrorType.response: + str = '请求返回失败'; + break; + case DioErrorType.cancel: + str = '请求取消'; + break; + case DioErrorType.other: + str = '请求其他错误'; + break; + } + return str; +} + +/// 自定义异常 +class AppException extends DioError { + final String _message; + final int _code; + AppException(this._code, this._message, StackTrace? theStackTrace, + {required super.requestOptions, super.type, super.error}) { + super.stackTrace = theStackTrace; + } + + @override + String toString() { + return "$_code$_message" + super.toString(); + } + + String getMessage() { + return _message; + } + + factory AppException.create(DioError error) { + switch (error.type) { + case DioErrorType.cancel: + { + return AppException(-1, "请求取消", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case DioErrorType.connectTimeout: + { + return AppException(-1, "连接超时", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case DioErrorType.sendTimeout: + { + return AppException(-1, "请求超时", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case DioErrorType.receiveTimeout: + { + return AppException(-1, "响应超时", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case DioErrorType.response: + { + try { + int? errCode = error.response!.statusCode; + // String errMsg = error.response.statusMessage; + // return ErrorEntity(code: errCode, message: errMsg); + switch (errCode) { + case 400: + { + return AppException(errCode!, "请求语法错误", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 401: + { + var currentContext = TheGlobal.navigatorKey.currentState?.overlay?.context; + if (currentContext != null) { + var routePath = ModalRoute.of(currentContext)?.settings; + if (routePath != null) { + } else { + if (TheGlobal.navigatorKey.currentContext != null) { + ExceptionHandle.toLogin(TheGlobal.navigatorKey.currentContext); + } + } + } + return AppException(errCode!, "登录信息过期,请重新登录", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 403: + { + return AppException(errCode!, "服务器拒绝执行", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 404: + { + return AppException(errCode!, "无法连接服务器", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 405: + { + return AppException(errCode!, "请求方法被禁止", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 500: + { + return AppException(errCode!, "服务器内部错误", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 502: + { + return AppException(errCode!, "无效的请求", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 503: + { + return AppException(errCode!, "服务器挂了", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + case 505: + { + return AppException(errCode!, "不支持HTTP协议请求", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + default: + { + // return ErrorEntity(code: errCode, message: "未知错误"); + return AppException(errCode!, error.response!.statusMessage!, error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + } + } on Exception catch (_) { + return AppException(-1, "未知错误", error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + } + default: + { + return AppException(-1, error.error.message, error.stackTrace, + requestOptions: error.requestOptions, type: error.type, error: error.error); + } + } + } +} + +class ExceptionHandle { + // 异常处理信息 + static void exceptionPrompt(BuildContext context, AppException err, {bool logicHandle = true}) { + ToastUtils.getFluttertoast( + context: context, + msg: err._message, + backgroundColor: Colors.grey[350], + toastLength: Toast.LENGTH_LONG, + ); + if (!logicHandle) return; + switch (err._code) { + case 401: + toLogin(context); // 重新前往登录 + break; + default: + } + } + + static void toLogin(context, {int timeer = 800}) { + /* setTimeOut( + timeer, + () => RouterManager.router.navigateTo(context, RouterManager.loginPath, clearStack: true), + );*/ + } +} + +// 这里是一个我单独写得soket错误实例,因为dio默认生成的是不允许修改message内容的,我只能自定义一个使用 +class MyDioSocketException extends SocketException { + String message; + + MyDioSocketException( + this.message, { + osError, + address, + port, + }) : super( + message, + osError: osError, + address: address, + port: port, + ); +} diff --git a/lib/common/store/app_storage_key.dart b/lib/common/store/app_storage_key.dart new file mode 100644 index 0000000..00f4975 --- /dev/null +++ b/lib/common/store/app_storage_key.dart @@ -0,0 +1,15 @@ +/// 用户 - 配置信息 + +// ignore_for_file: constant_identifier_names +class AppStorageKey { + /// 登录用户的基本信息 + static const String STORAGE_USER_INFO = 'user_info'; + + /// 登录用户的token + static const String STORAGE_USER_TOKEN = 'APP:TOKEN'; + + /// 用户输入过的手机号码 + static const String STORAGE_USER_MOBILE = 'user_mobile'; + + +} diff --git a/lib/common/store/user_store.dart b/lib/common/store/user_store.dart new file mode 100644 index 0000000..1a39ecf --- /dev/null +++ b/lib/common/store/user_store.dart @@ -0,0 +1,48 @@ +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/job/user_info.dart'; +import 'package:school_asignment_app/common/store/app_storage_key.dart'; +import 'package:school_asignment_app/common/utils/storage.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; + +class UserStore extends GetxController { + static UserStore get to => Get.find(); + /// 是否登录 + final isLogin = false.obs; + String token = ''; + /// 用户信息 + Rx userInfo = Rx(UserInfo()); + + void init() { + /*token = StorageService.to.read(AppStorageKey.STORAGE_USER_TOKEN) ?? ''; + try { + var userInfoJson = StorageService.to.read(AppStorageKey.STORAGE_USER_INFO); + if (userInfoJson != null) { + userInfo.value = UserInfo.fromJson(userInfoJson); + } else { + userInfo.value = UserInfo(); + } + } catch (err, t) { + userInfo.value = UserInfo(); + StorageService.to.remove(AppStorageKey.STORAGE_USER_INFO); + } + if (token.isNotEmpty && userInfo.value.loginName.isNotEmpty) { + isLogin.value = true; + }else{ + isLogin.value = false; + Get.toNamed(Routes.login); + }*/ + + + } + + /// 保存 token + void setToken(String token) { + token = token; + StorageService.to.write(AppStorageKey.STORAGE_USER_TOKEN, token); + } + /// 保存 token + void setUserInfo(UserInfo info) { + userInfo.value = info; + StorageService.to.write(AppStorageKey.STORAGE_USER_INFO, info); + } +} diff --git a/lib/common/the_global.dart b/lib/common/the_global.dart new file mode 100644 index 0000000..63cb902 --- /dev/null +++ b/lib/common/the_global.dart @@ -0,0 +1,6 @@ +import 'package:flutter/material.dart'; + +// 全局 GlobalKey +class TheGlobal { + static GlobalKey navigatorKey = GlobalKey(); +} \ No newline at end of file diff --git a/lib/common/utils/common_utils.dart b/lib/common/utils/common_utils.dart new file mode 100644 index 0000000..e7bb2a8 --- /dev/null +++ b/lib/common/utils/common_utils.dart @@ -0,0 +1,21 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 16:59:53 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-13 17:00:56 + * @FilePath: \marking_app\lib\utils\common_utils.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'dart:convert'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; + +class CommonUtils { + // md5 加密 + static String generateMD5(String data) { + var content = new Utf8Encoder().convert(data); + var digest = md5.convert(content); + // 这里其实就是 digest.toString() + return hex.encode(digest.bytes); + } +} diff --git a/lib/common/utils/storage.dart b/lib/common/utils/storage.dart new file mode 100644 index 0000000..dd4d5f8 --- /dev/null +++ b/lib/common/utils/storage.dart @@ -0,0 +1,30 @@ +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +class StorageService extends GetxService { + static StorageService get to => Get.find(); + late final GetStorage _getStorage; + + get storage => _getStorage; + + Future init() async { + await GetStorage.init(); + _getStorage = GetStorage(); + } + + T? read(String key) { + return _getStorage.read(key); + } + + Future write(String key, dynamic value) async { + return await _getStorage.write(key, value); + } + + Future remove(String key) async { + return await _getStorage.remove(key); + } + + bool hasData(String key) { + return _getStorage.hasData(key); + } +} diff --git a/lib/common/utils/toast_utils.dart b/lib/common/utils/toast_utils.dart new file mode 100644 index 0000000..73b7373 --- /dev/null +++ b/lib/common/utils/toast_utils.dart @@ -0,0 +1,82 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-07-13 16:31:05 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-07-28 11:56:13 + * @FilePath: \marking_app\lib\utils\toast_utils.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ + +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + +class ToastUtils { + static void getFluttertoast({ + required BuildContext context, + required String msg, + Toast? toastLength, + int timeInSecForIosWeb = 1, + double? fontSize, + ToastGravity? gravity, + Color? backgroundColor, + Color? textColor, + }) { + Fluttertoast.showToast( + msg: msg, + toastLength: toastLength ?? Toast.LENGTH_SHORT, + gravity: gravity ?? ToastGravity.CENTER, + timeInSecForIosWeb: timeInSecForIosWeb, + backgroundColor: backgroundColor ?? Theme.of(context).primaryColor, + textColor: textColor ?? Colors.white, + fontSize: fontSize ?? 16.sp, + ); + } + + static void getErrFluttertoast({ + required BuildContext context, + required String msg, + ToastGravity gravity = ToastGravity.BOTTOM, + Color backgroundColor = Colors.grey, + Toast? toastLength, + int timeInSecForIosWeb = 1, + double? fontSize, + Color? textColor, + }) { + ToastUtils.getFluttertoast( + context: context, + msg: msg, + toastLength: toastLength ?? Toast.LENGTH_SHORT, + gravity: gravity, + timeInSecForIosWeb: timeInSecForIosWeb, + backgroundColor: backgroundColor, + textColor: textColor ?? Colors.white, + fontSize: fontSize ?? 16.sp, + ); + } + + static showError(String showMsg) { + EasyLoading.showError(showMsg); + } + + static showLoading() { + EasyLoading.show(status: 'loading...'); + } + + static showInfo(String showMsg, {Duration? duration}) { + EasyLoading.showInfo(showMsg, duration: duration); + } + + static showInfoSimple(String showMsg, int microseconds) { + EasyLoading.showInfo(showMsg, duration: Duration(microseconds: microseconds)); + } + + static showSuccess(String showMsg, {Duration? duration}) { + EasyLoading.showSuccess(showMsg, duration: duration); + } + + static dismiss() { + EasyLoading.dismiss(); + } +} diff --git a/lib/common/utils/utils.dart b/lib/common/utils/utils.dart new file mode 100644 index 0000000..101e553 --- /dev/null +++ b/lib/common/utils/utils.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class Utils{ + Utils._internal(); + + /// 关闭键盘 + static void hideKeyboard() { + FocusScopeNode? currentFocus = Get.focusScope?.nearestScope; + if (currentFocus == null) { + return; + } + if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) { + FocusManager.instance.primaryFocus?.unfocus(); + } + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..dda52c2 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/config/app_config.dart'; +import 'package:school_asignment_app/common/config/colorUtils.dart'; +import 'package:school_asignment_app/common/store/user_store.dart'; +import 'package:school_asignment_app/common/utils/storage.dart'; +import 'package:school_asignment_app/common/utils/utils.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; + + +void main() async{ +// 在测试模式下运行Get + Get.testMode = true; + /// 初始化本地存储 + StorageService storageService = StorageService(); + await storageService.init(); + Get.put(storageService); + + /// 初始化UserStore + UserStore userStore = UserStore(); + userStore.init(); + Get.put(userStore); + + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return ScreenUtilInit( + designSize: const Size(AppConfig.UI_WIDTH, AppConfig.UI_HEIGHT), + builder: (BuildContext context, Widget? child) => GetMaterialApp( + title: '作业', + theme: ThemeData( + brightness: Brightness.light, + primarySwatch: createMaterialColor(const Color.fromRGBO(46, 91, 255, 1)), + // textTheme: Typography.englishLike2018.apply(fontSizeFactor: 1.sp,), + primaryTextTheme: TextTheme( + bodyLarge: TextStyle(fontSize: 14.sp, color: Colors.black87), + ), + useMaterial3: true, + ), + enableLog: true, + logWriterCallback: (text, {bool isError = false}) { + // isError ? LoggerUtils.e(text) : LoggerUtils.i(text); + }, + //默认专场动画 + defaultTransition: Transition.fade, + //初始化路由页面 + initialRoute: Routes.startPage, + /// 路由表 + getPages: AppPages.pages, + builder: EasyLoading.init( + builder: (context, child) { + return MediaQuery( + //Setting font does not change with system font size + data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), + child: Scaffold( + body: GestureDetector( + onTap: () => Utils.hideKeyboard(), + child: child, + ), + ), + ); + }, + ), + // home: const MyHomePage(title: 'Flutter Demo Home Page'), + ), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // TRY THIS: Try changing the color here to a specific color (to + // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar + // change color while the other colors stay the same. + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + // + // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" + // action in the IDE, or press "p" in the console), to see the + // wireframe for each widget. + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'You have pushed the button this many times:', + ), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/lib/page/global_widget/my_text.dart b/lib/page/global_widget/my_text.dart new file mode 100644 index 0000000..dd62894 --- /dev/null +++ b/lib/page/global_widget/my_text.dart @@ -0,0 +1,33 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: 2022-08-01 14:11:37 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-08-02 15:34:34 + * @FilePath: \marking_app\lib\utils\my_text.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +import 'package:flutter/cupertino.dart'; +import 'package:school_asignment_app/common/config/colorUtils.dart'; + +// 快捷Text使用 +Text quickText(text, + {double? size, + Color color = CommonColors.defaultColor, + TextAlign? align, + FontWeight? fontWeight, + TextOverflow overflow = TextOverflow.ellipsis, + int maxLines = 1, + TextDecoration decoration = TextDecoration.none}) { + return Text( + text.toString(), + textAlign: align, + maxLines: maxLines, + overflow: overflow, + style: TextStyle( + decoration: decoration, + fontSize: size, + color: color, + fontWeight: fontWeight, + ), + ); +} diff --git a/lib/page/global_widget/start_page.dart b/lib/page/global_widget/start_page.dart new file mode 100644 index 0000000..647d502 --- /dev/null +++ b/lib/page/global_widget/start_page.dart @@ -0,0 +1,58 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/job/user_info.dart'; +import 'package:school_asignment_app/common/store/app_storage_key.dart'; +import 'package:school_asignment_app/common/utils/storage.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; + +class StartPage extends StatefulWidget { + const StartPage({Key? key}) : super(key: key); + + @override + State createState() => _StartPageState(); +} + +class _StartPageState extends State { + + @override + void initState(){ + super.initState(); + var token = StorageService.to.read(AppStorageKey.STORAGE_USER_TOKEN) ?? ''; + UserInfo userInfo = UserInfo(); + try { + var userInfoJson = StorageService.to.read(AppStorageKey.STORAGE_USER_INFO); + if (userInfoJson != null) { + userInfo = UserInfo.fromJson(userInfoJson); + } else { + userInfo = UserInfo(); + } + } catch (err, t) { + userInfo = UserInfo(); + StorageService.to.remove(AppStorageKey.STORAGE_USER_INFO); + } + + + if (token.isNotEmpty && userInfo.loginName.isNotEmpty) { + Future.delayed(const Duration(milliseconds: 200)).then((e) { + Get.toNamed(Routes.home); + }); + }else{ + Future.delayed(const Duration(milliseconds: 200)).then((e) { + Get.toNamed(Routes.login); + }); + + } + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Positioned( + bottom: 40.r, + child: Text('启动中...',style: TextStyle(fontSize: 16.r,color: const Color(0xFF6888FD)),)) + ] + ); + } +} diff --git a/lib/page/home_page/home_binding.dart b/lib/page/home_page/home_binding.dart new file mode 100644 index 0000000..f5529e7 --- /dev/null +++ b/lib/page/home_page/home_binding.dart @@ -0,0 +1,10 @@ +import 'package:get/get.dart'; + +import 'home_logic.dart'; + +class HomeBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => HomeLogic()); + } +} diff --git a/lib/page/home_page/home_logic.dart b/lib/page/home_page/home_logic.dart new file mode 100644 index 0000000..749bfab --- /dev/null +++ b/lib/page/home_page/home_logic.dart @@ -0,0 +1,7 @@ +import 'package:get/get.dart'; + +import 'home_state.dart'; + +class HomeLogic extends GetxController { + final HomeState state = HomeState(); +} diff --git a/lib/page/home_page/home_state.dart b/lib/page/home_page/home_state.dart new file mode 100644 index 0000000..6953451 --- /dev/null +++ b/lib/page/home_page/home_state.dart @@ -0,0 +1,5 @@ +class HomeState { + HomeState() { + ///Initialize variables + } +} diff --git a/lib/page/home_page/home_view.dart b/lib/page/home_page/home_view.dart new file mode 100644 index 0000000..25dedd1 --- /dev/null +++ b/lib/page/home_page/home_view.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/store/app_storage_key.dart'; +import 'package:school_asignment_app/common/utils/storage.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; + +import 'home_logic.dart'; + +class HomePage extends StatefulWidget { + const HomePage({Key? key}) : super(key: key); + + @override + State createState() => _HomePageState(); +} + +class _HomePageState extends State { + final logic = Get.find(); + final state = Get.find().state; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: 20.r), + child: Column( + children: [ + Text('home',style: TextStyle(fontSize: 20.sp,color: Colors.red),), + InkWell( + onTap: (){ + StorageService.to.remove(AppStorageKey.STORAGE_USER_TOKEN); + StorageService.to.remove(AppStorageKey.STORAGE_USER_INFO); + Get.offAllNamed(Routes.login); + }, + child: Text('退出',style: TextStyle(fontSize: 20.sp,color: Colors.black),)), + ], + ), + ); + } + + @override + void dispose() { + Get.delete(); + super.dispose(); + } +} \ No newline at end of file diff --git a/lib/page/login_page/children/agreement_page.dart b/lib/page/login_page/children/agreement_page.dart new file mode 100644 index 0000000..1bc7184 --- /dev/null +++ b/lib/page/login_page/children/agreement_page.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/const_text.dart'; +import 'package:school_asignment_app/page/global_widget/my_text.dart'; + +// 协议富文本 +class AgreementPage extends StatelessWidget { + + const AgreementPage({super.key}); + + @override + Widget build(BuildContext context) { + AGREEMENT_KEY type = AGREEMENT_KEY.values.byName(Get.arguments['type']); + AgreementClass agreement = AGREEMENT_MAP[type]!; + return Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).primaryColor, + title: quickText(agreement.title,color: Colors.white), + ), + body: ListView( + padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 8.h), + children: [ + HtmlWidget(agreement.richText,textStyle:const TextStyle(color: Colors.black)), + ], + ), + ); + } +} diff --git a/lib/page/login_page/login_binding.dart b/lib/page/login_page/login_binding.dart new file mode 100644 index 0000000..64200bb --- /dev/null +++ b/lib/page/login_page/login_binding.dart @@ -0,0 +1,10 @@ +import 'package:get/get.dart'; + +import 'login_logic.dart'; + +class LoginBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => LoginLogic()); + } +} diff --git a/lib/page/login_page/login_logic.dart b/lib/page/login_page/login_logic.dart new file mode 100644 index 0000000..2135ad6 --- /dev/null +++ b/lib/page/login_page/login_logic.dart @@ -0,0 +1,148 @@ +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/api/user_api.dart'; +import 'package:school_asignment_app/common/job/common/base_structure_result.dart'; +import 'package:school_asignment_app/common/job/user_info.dart'; +import 'package:school_asignment_app/common/job/user_login.dart'; +import 'package:school_asignment_app/common/store/user_store.dart'; +import 'package:school_asignment_app/common/utils/common_utils.dart'; +import 'package:school_asignment_app/common/utils/toast_utils.dart'; +import 'package:school_asignment_app/common/utils/utils.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; + +import 'login_state.dart'; + +class LoginLogic extends GetxController { + final LoginState state = LoginState(); + + @override + void onReady() { + // TODO: implement onReady + super.onReady(); + } + void onInit(){ + super.onInit(); + state.userNameController = TextEditingController()..addListener(userNameListener); + state.passwordController = TextEditingController(); + state.pwdFocus = FocusNode(); + state.theFocus = FocusNode(); + } + void userNameListener() { + String userName = state.userNameController.text; + int useNameLength = userName.length; + bool hasNameValNew = useNameLength > 0; + if (hasNameValNew != state.hasNameVal) state.hasNameVal = hasNameValNew; + const isProd = bool.fromEnvironment('dart.vm.product'); + if (!isProd && useNameLength == 11) { + state.passwordController.text = userName.substring(useNameLength - 6); + } + } + void showPassword() { + state.isShowPwd.value = !state.isShowPwd.value; + } +// 前往登录 + void toLogin() async { + if (!state.canLogin.value) return; + + state.canLogin.value = false; + + void toMsg(msg) { + ToastUtils.showError(msg); + state.canLogin.value = true; + } + + Utils.hideKeyboard(); + + String userName = state.userNameController.text.trim(); + String userPwd = state.passwordController.text.trim(); + if (userName == '') return toMsg('请填写用户账号'); + if (userPwd == '') return toMsg('请填写密码再试'); + if (!state.readAgreement.value) return toMsg('请阅读用户协议'); + + String userPwdMd5 = CommonUtils.generateMD5(userPwd); + EasyLoading.show(status: 'loading...'); + try { + BaseStructureResult resultData = await UserApi.toLogin(loginName:userName,password:userPwdMd5); + + + // BaseStructureResult resultData = await client.toLogin(UserLoginParams(userName, userPwdMd5)); + UserLogin? userData = + resultData.code == 200 && resultData.data != null ? UserLogin.fromJson(resultData.data) : null; + + print(resultData.code); + if (resultData.code != 200 || userData?.accessToken == null || userData?.accessToken == '') { + return toMsg(resultData.message ?? '登录失败,请重试'); + } + + UserStore.to.setToken(userData!.accessToken); + state.canLogin.value = true; + + BaseStructureResult userRes = await UserApi.getUserInfo(); + print('99999999999'); + print(userRes.data!.userName); + if (userRes.code != 200 || userRes.data == null) { + throw Exception('登录失败,请重试'); + }else{ + UserStore.to.setUserInfo(userRes.data!); + Get.offAllNamed(Routes.home); + } + + + /* fastData.setUser(userRes.data!).then((value) { + // 记住密码 + if (keepPwd) { + fastData.setUserPwdAndAccount({'pwd': userPwd, 'account': userName}); + } + // 更新 + ref.read(userProvider.notifier).initUserInfo(); + ref.read(userTokenProvider.notifier).initToken(); + + // 跳转登录页 + Get.toNamed(Routes.login); + // RouterManager.router.navigateTo(context, RouterManager.root, clearStack: true, transition: getTransition()); + });*/ + } catch (e) { + // toPrint(val: e.toString()); + String? msg; + if (e is DioError) { + DioErrorType errorType = e.type; + switch (errorType) { + case DioErrorType.connectTimeout: + msg = '连接超时,请检查网络再重试'; + break; + case DioErrorType.sendTimeout: + msg = '发送时间超时,请重试'; + break; + case DioErrorType.receiveTimeout: + msg = '接收数据超时,请重试'; + break; + case DioErrorType.response: + // TODO: Handle this case. + break; + case DioErrorType.cancel: + // TODO: Handle this case. + break; + case DioErrorType.other: + // TODO: Handle this case. + break; + } + } + // FastData.getInstance().cleanShared(); + return toMsg(msg ?? '登录失败,请重试'); + } finally { + EasyLoading.dismiss(); + } + } + @override + void dispose() { + super.dispose(); + state.userNameController + ..removeListener(userNameListener) + ..dispose(); + state.passwordController.dispose(); + state.pwdFocus.dispose(); + state.theFocus.dispose(); + } +} diff --git a/lib/page/login_page/login_state.dart b/lib/page/login_page/login_state.dart new file mode 100644 index 0000000..5933131 --- /dev/null +++ b/lib/page/login_page/login_state.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class LoginState { + LoginState() { + ///Initialize variables + } + + late final FocusNode pwdFocus; // 密码 + late final FocusNode theFocus; + //文本输入框控制器 + late final TextEditingController userNameController; + late final TextEditingController passwordController; + bool hasNameVal = false; + late RxBool isShowPwd = true.obs; + late RxBool keepPwd = false.obs; + late RxBool canLogin = true.obs; + late RxBool readAgreement = true.obs; +} diff --git a/lib/page/login_page/login_view.dart b/lib/page/login_page/login_view.dart new file mode 100644 index 0000000..0bfc893 --- /dev/null +++ b/lib/page/login_page/login_view.dart @@ -0,0 +1,304 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:school_asignment_app/common/const_text.dart'; +import 'package:school_asignment_app/common/utils/utils.dart'; +import 'package:school_asignment_app/page/global_widget/my_text.dart'; +import 'package:school_asignment_app/routes/app_pages.dart'; + + +import 'login_logic.dart'; + +class LoginPage extends StatefulWidget { + const LoginPage({Key? key}) : super(key: key); + + @override + State createState() => _LoginPageState(); +} + +class _LoginPageState extends State { + final logic = Get.find(); + final state = Get + .find() + .state; + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + Utils.hideKeyboard(); + // FocusScope.of(context).requestFocus(state.theFocus); + }, + child: AnnotatedRegion( + value: const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + systemNavigationBarIconBrightness: Brightness.light, + statusBarIconBrightness: Brightness.light, + statusBarBrightness: Brightness.dark, + ), + child: Scaffold( + backgroundColor: Colors.transparent, + resizeToAvoidBottomInset: false, + body: Container( + width: double.infinity, + height: double.infinity, + alignment: Alignment.center, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage('assets/images/login_bgi.png'), + fit: BoxFit.fill, // 完全填充 + ), + ), + child: SingleChildScrollView( + child: Column( + children: [ + Container( + width: 86.w, + height: 86.w, + alignment: Alignment.center, + child: SizedBox( + height: 86.w, + width: 86.w, + child: Image.asset( + 'assets/images/logo.png', fit: BoxFit.cover), + ), + ), + Container( + margin: EdgeInsets.symmetric( + horizontal: 32.w, vertical: 24.h), + padding: EdgeInsets.only( + top: 34.h, bottom: 16.h, left: 22.w, right: 22.w), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(width: 1.w, color: Colors.white), + borderRadius: BorderRadius.all(Radius.circular(10.w)), + boxShadow: const [ + BoxShadow( + color: Color.fromRGBO(46, 91, 255, 0.1), + offset: Offset.zero, //阴影y轴偏移量 + blurRadius: 100, //阴影模糊程度 + spreadRadius: 100, //阴影扩散程度 + ) + ], + ), + child: Column(children: [ + TextField( + controller: state.userNameController, + maxLines: 1, + maxLength: 20, + textInputAction: TextInputAction.next, + onEditingComplete: () { + Get.focusScope?.nextFocus(); + // FocusScope.of(context).requestFocus(_pwdFocus); + }, + style: TextStyle( + color: const Color.fromRGBO(80, 87, 103, 1), + fontSize: 15.sp, + ), + decoration: InputDecoration( + hintText: "请输入账号", + hintStyle: TextStyle(fontSize: 16.sp, + color: const Color.fromRGBO(153, 153, 153, 1)), + labelText: "账号", + labelStyle: TextStyle(fontSize: 16.sp, + color: const Color.fromRGBO(148, 163, 182, 1)), + suffixIcon: !state.hasNameVal + ? null + : Transform.translate( + offset: Offset(10, 10), // 根据原始组件的padding值来设置偏移量 + child: IconButton( + alignment: Alignment.center, + padding: EdgeInsets.zero, + icon: Icon( + Icons.highlight_off_sharp, + color: Colors.grey, + size: 16.r, + ), + onPressed: () { + state.userNameController.clear(); // 清空文本框内容 + state.passwordController.clear(); + }, + ), + ), + ), + ), + Obx(() { + return TextField( + focusNode: state.pwdFocus, + controller: state.passwordController, + keyboardType: TextInputType.number, + maxLines: 1, + obscureText: state.isShowPwd.value, + //隐藏密码显示 + textInputAction: TextInputAction.go, + // onSubmitted: (val) => toLogin(), + style: TextStyle( + color: const Color.fromRGBO(80, 87, 103, 1), + fontSize: 15.sp, + ), + decoration: InputDecoration( + hintText: "请输入密码", + suffix: GestureDetector( + onTap: logic.showPassword, + child: Icon( + Icons.remove_red_eye, + color: state.isShowPwd.value ? Theme + .of(context) + .primaryColor : Colors.grey, + ), + ), + hintStyle: TextStyle(fontSize: 16.sp, + color: const Color.fromRGBO( + 153, 153, 153, 1)), + labelText: "密码", + isDense: true, + labelStyle: TextStyle(fontSize: 16.sp, + color: const Color.fromRGBO( + 148, 163, 182, 1)), + ), + ); + }), + SizedBox( + height: 12.h, + ), + Row( + children: [ + Container( + width: 30.w, + padding: EdgeInsets.only(right: 10.w), + child: Obx(() { + return Checkbox( + activeColor: Theme + .of(context) + .primaryColor, + checkColor: Colors.white, + value: state.keepPwd.value, + onChanged: (value) { + Get.focusScope?.nextFocus(); + /* FocusScope.of(context).requestFocus( + state.pwdFocus); + FocusScope.of(context).requestFocus( + state.theFocus);*/ + state.keepPwd.value = value ?? false; + }, + ); + }), + ), + InkWell( + onTap: () { + Utils.hideKeyboard(); + /*Get.focusScope?.nextFocus(); + Get.focusScope?.nextFocus();*/ + + /* FocusScope.of(context).requestFocus( + state.pwdFocus); + FocusScope.of(context).requestFocus( + state.theFocus);*/ + state.keepPwd.value = !state.keepPwd.value; + }, + child: Text( + '记住密码', + style: TextStyle( + fontSize: 14.sp, + color: const Color.fromRGBO(148, 163, 182, 1), + ), + ), + ), + ], + ), + InkWell( + onTap: () { + logic.toLogin(); + // Get.toNamed(Routes.home); + }, + child: Obx(() { + return Container( + margin: EdgeInsets.symmetric(vertical: 10.h), + decoration: BoxDecoration( + color: state.canLogin.value ? const Color.fromRGBO( + 9, 105, 246, 1) : Colors.grey, + boxShadow: [ + BoxShadow( + color: const Color.fromRGBO( + 46, 91, 255, 0.5), + offset: Offset(6.w, 10.h), //阴影y轴偏移量 + blurRadius: 14, //阴影模糊程度 + spreadRadius: 0.5, //阴影扩散程度 + ) + ], + borderRadius: BorderRadius.all( + Radius.circular(8.w), + ), + ), + alignment: Alignment.center, + width: double.infinity, + height: 50.h, + child: Text( + '登 录', + style: TextStyle( + fontSize: 16.sp, color: Colors.white), + ), + ); + }), + ), + Row( + children: [ + Container( + width: 30.w, + padding: EdgeInsets.only(right: 10.w), + child: Obx(() { + return Checkbox( + activeColor: Colors.deepOrangeAccent, + checkColor: Colors.white, + value: state.readAgreement.value, + onChanged: (value) { + Utils.hideKeyboard(); + /* FocusScope.of(context).requestFocus( + state.pwdFocus); + FocusScope.of(context).requestFocus( + state.theFocus);*/ + state.readAgreement.value = value ?? false; + }, + ); + }), + ), + InkWell( + onTap: () { + Get.toNamed(Routes.agreementPage, + arguments: {"type": AGREEMENT_KEY + .USER_AGREEMENT.name}); + }, + child: quickText('请仔细阅读', size: 13.sp), + ), + InkWell( + onTap: () { + Get.toNamed(Routes.agreementPage, + arguments: {"type": AGREEMENT_KEY + .USER_AGREEMENT.name}); + }, + child: Text( + '《用户协议》', + style: TextStyle(fontSize: 14.r, + color: Colors.deepOrangeAccent), + ), + ), + ], + ), + ]), + ) + ], + ), + )), + ), + ), + ); + } + + @override + void dispose() { + Get.delete(); + super.dispose(); + } +} \ No newline at end of file diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart new file mode 100644 index 0000000..f39a1a3 --- /dev/null +++ b/lib/routes/app_pages.dart @@ -0,0 +1,16 @@ +import 'package:get/get.dart'; +import 'package:school_asignment_app/page/global_widget/start_page.dart'; +import 'package:school_asignment_app/page/home_page/home_binding.dart'; +import 'package:school_asignment_app/page/home_page/home_view.dart'; +import 'package:school_asignment_app/page/login_page/children/agreement_page.dart'; +import 'package:school_asignment_app/page/login_page/login_binding.dart'; +import 'package:school_asignment_app/page/login_page/login_view.dart'; +part 'app_routes.dart'; +abstract class AppPages { +static final pages=[ + GetPage(name: Routes.login, page: () => const LoginPage(), binding: LoginBinding(), transition: Transition.noTransition), + GetPage(name: Routes.agreementPage, page: () => const AgreementPage(), binding: LoginBinding(), transition: Transition.noTransition), + GetPage(name: Routes.home, page: () => const HomePage(), binding: HomeBinding(), transition: Transition.noTransition), + GetPage(name: Routes.startPage, page: () => const StartPage(), transition: Transition.noTransition), +]; +} \ No newline at end of file diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart new file mode 100644 index 0000000..bc6f86c --- /dev/null +++ b/lib/routes/app_routes.dart @@ -0,0 +1,8 @@ +part of 'app_pages.dart'; + +abstract class Routes { + static const login = '/login'; + static const agreementPage = '/agreementPage'; + static const home = '/home'; + static const startPage = '/startPage'; +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..23a211b --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,882 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + url: "https://pub.dev" + source: hosted + version: "64.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + url: "https://pub.dev" + source: hosted + version: "6.2.0" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + url: "https://pub.dev" + source: hosted + version: "2.4.8" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + url: "https://pub.dev" + source: hosted + version: "7.3.0" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + url: "https://pub.dev" + source: hosted + version: "8.9.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + url: "https://pub.dev" + source: hosted + version: "1.17.1" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: b74247fad72c171381dbe700ca17da24deac637ab6d43c343b42867acb95c991 + url: "https://pub.dev" + source: hosted + version: "3.0.6" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: cf1d1c28f4416f8c654d7dc3cd638ec586076255d407cef3ddbdaf178272a71a + url: "https://pub.dev" + source: hosted + version: "1.2.4" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: "direct main" + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + csslib: + dependency: transitive + description: + name: csslib + sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + url: "https://pub.dev" + source: hosted + version: "0.7.10" + dio: + dependency: "direct main" + description: + name: dio + sha256: "7d328c4d898a61efc3cd93655a0955858e29a0aa647f0f9e02d59b3bb275e2e8" + url: "https://pub.dev" + source: hosted + version: "4.0.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" + flutter_easyloading: + dependency: "direct main" + description: + name: flutter_easyloading + sha256: ba21a3c883544e582f9cc455a4a0907556714e1e9cf0eababfcb600da191d17c + url: "https://pub.dev" + source: hosted + version: "3.0.5" + flutter_easyrefresh: + dependency: "direct main" + description: + name: flutter_easyrefresh + sha256: "5d161ee5dcac34da9065116568147d742dd25fb9bff3b10024d9054b195087ad" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "0a122936b450324cbdfd51be0819cc6fcebb093eb65585e9cd92263f7a1a8a39" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + flutter_spinkit: + dependency: transitive + description: + name: flutter_spinkit + sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e + url: "https://pub.dev" + source: hosted + version: "5.2.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_widget_from_html_core: + dependency: "direct main" + description: + name: flutter_widget_from_html_core + sha256: "22140caa191cb4bba0fe4d5e4ad875c7e8a9ba47d61517f56d733019cf76396d" + url: "https://pub.dev" + source: hosted + version: "0.10.6" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: dfdde255317af381bfc1c486ed968d5a43a2ded9c931e87cbecd88767d6a71c1 + url: "https://pub.dev" + source: hosted + version: "8.2.4" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + functional_widget_annotation: + dependency: "direct main" + description: + name: functional_widget_annotation + sha256: f0612079cb7e226b7be32b473bdaf85fe680370886c0c13ea69a102ccc17a0c7 + url: "https://pub.dev" + source: hosted + version: "0.10.0" + get: + dependency: "direct main" + description: + name: get + sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + get_storage: + dependency: "direct main" + description: + name: get_storage + sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + html: + dependency: transitive + description: + name: html + sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + url: "https://pub.dev" + source: hosted + version: "0.15.4" + http: + dependency: transitive + description: + name: http + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + url: "https://pub.dev" + source: hosted + version: "4.8.1" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + url: "https://pub.dev" + source: hosted + version: "6.7.1" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + logger: + dependency: "direct main" + description: + name: logger + sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + url: "https://pub.dev" + source: hosted + version: "0.12.15" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" + source: hosted + version: "0.2.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + package_info: + dependency: "direct main" + description: + name: package_info + sha256: "6c07d9d82c69e16afeeeeb6866fe43985a20b3b50df243091bfc4a4ad2b03b75" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" + photo_view: + dependency: "direct main" + description: + name: photo_view + sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb" + url: "https://pub.dev" + source: hosted + version: "0.14.0" + platform: + dependency: transitive + description: + name: platform + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" + url: "https://pub.dev" + source: hosted + version: "3.1.4" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + source_span: + dependency: transitive + description: + name: source_span + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" + source: hosted + version: "1.9.1" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 + url: "https://pub.dev" + source: hosted + version: "2.3.2" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + url: "https://pub.dev" + source: hosted + version: "0.5.1" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" + url: "https://pub.dev" + source: hosted + version: "5.0.9" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.0.1 <4.0.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..fb0a6b8 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,123 @@ +name: school_asignment_app +description: A new Flutter project. +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=3.0.1 <4.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + # 路由、依赖、状态插件 + get: ^4.6.5 + # loading插件 + flutter_easyloading: ^3.0.5 + # 日志插件 + logger: ^1.1.0 + # 屏幕尺寸计算插件 + flutter_screenutil: 5.7.0 + # http请求插件 + dio: ^4.0.6 + # 网络缓存图片 + cached_network_image: ^3.2.1 + # 上拉加载和下拉刷新的组件 + flutter_easyrefresh: ^2.2.2 + photo_view: ^0.14.0 + # 加密验签插件,支持SHA MD5 HMAC + crypto: ^3.0.2 + json_annotation: ^4.8.1 + # 获取app版本号 + package_info: ^2.0.2 + # 网络监控 + connectivity_plus: ^3.0.6 + # toast组件用于系统尚未初始化完成时 + fluttertoast: ^8.0.9 + # + functional_widget_annotation: ^0.10.0 + flutter_widget_from_html_core: ^0.10.3 + # APP内存及本地存储插件 + get_storage: ^2.0.3 + + +dev_dependencies: + flutter_test: + sdk: flutter + json_serializable: ^6.3.1 + build_runner: ^2.4.8 + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + assets: + - assets/images/ + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..e1a7acc --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:school_asignment_app/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +}