From 4bda32fb5a3eb4ae3dc30f91f7bcf7a637410e2b Mon Sep 17 00:00:00 2001 From: Hugo <24639535+kr4xkan@users.noreply.github.com> Date: Tue, 4 Jan 2022 23:36:10 +0100 Subject: [PATCH] =?UTF-8?q?A=20little=20sweep=20here=20and=20there=20?= =?UTF-8?q?=F0=9F=A7=B9=20(#1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * up and working for iOS * updating dart to null safety and Android compatibility * feat: task implementation --- .gitignore | 6 +- README.md | 4 + android/app/build.gradle | 2 +- android/app/google-services.json | 40 - android/app/src/main/AndroidManifest.xml | 1 + .../com/litarvan/epilyon/Application.kt | 11 +- assets/images/default_thumb.jpg | Bin 0 -> 3073 bytes ios/Flutter/AppFrameworkInfo.plist | 52 +- ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Podfile | 41 + ios/Podfile.lock | 143 +++ ios/Runner.xcodeproj/project.pbxproj | 1123 +++++++++-------- .../contents.xcworkspacedata | 14 +- .../contents.xcworkspacedata | 17 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + ios/Runner/Info.plist | 90 +- lib/api_url.dart | 4 +- lib/auth.dart | 135 +- lib/data.dart | 285 +++-- lib/delegates.dart | 55 +- lib/firebase.dart | 45 +- lib/main.dart | 34 +- lib/mcq.dart | 30 +- lib/mimos.dart | 52 +- lib/pages.dart | 102 +- lib/pages/about.dart | 2 +- lib/pages/base.dart | 14 +- lib/pages/login.dart | 8 +- lib/pages/main.dart | 344 ++--- lib/pages/manage/add_mimos_dialog.dart | 71 +- lib/pages/manage/manage.dart | 264 ++-- lib/pages/mcq/mcq_history.dart | 145 +-- lib/pages/mcq/mcq_result.dart | 116 +- lib/pages/mimos.dart | 30 +- lib/pages/ms_login.dart | 62 +- lib/pages/task/task_detail.dart | 66 + lib/pages/task/task_list.dart | 145 +++ lib/task.dart | 38 + lib/widgets/button.dart | 2 +- lib/widgets/card.dart | 4 +- lib/widgets/content.dart | 14 +- lib/widgets/dialogs.dart | 52 +- lib/widgets/dropdown.dart | 8 +- lib/widgets/refresh_button.dart | 4 +- lib/widgets/text_form_field.dart | 12 +- pubspec.lock | 272 ++-- pubspec.yaml | 25 +- 48 files changed, 2282 insertions(+), 1712 deletions(-) delete mode 100644 android/app/google-services.json create mode 100644 assets/images/default_thumb.jpg create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 lib/pages/task/task_detail.dart create mode 100644 lib/pages/task/task_list.dart create mode 100644 lib/task.dart diff --git a/.gitignore b/.gitignore index ac246c1..7f34bed 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ # 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/ +.vscode/ # Flutter/Dart/Pub related **/doc/api/ @@ -35,3 +35,7 @@ lib/generated_plugin_registrant.dart # Exceptions to above rules. !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages + +# Firebase files +android/app/google-services.json +ios/Runner/GoogleService-Info.plist \ No newline at end of file diff --git a/README.md b/README.md index 90ae13d..cc7e0cc 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,13 @@ - [Flutter SDK](https://flutter.dev/docs/get-started/install) - Android Studio (for Android) or XCode (for iOS) - [Epilyon Server](https://github.com/epilyon/epilyon_server) ran somewhere +- Firebase app ### Building +- Add `android/app/google-services.json` +- Add `ios/Runner/GoogleService-Info.plist` + - Android : Follow [those instructions](https://flutter.dev/docs/deployment/android) - iOS : Follow [those ones](https://flutter.dev/docs/deployment/ios) diff --git a/android/app/build.gradle b/android/app/build.gradle index 3024a47..017701d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -44,7 +44,7 @@ android { defaultConfig { applicationId "com.litarvan.epilyon" - minSdkVersion 16 + minSdkVersion 19 targetSdkVersion 28 versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/android/app/google-services.json b/android/app/google-services.json deleted file mode 100644 index 442b44d..0000000 --- a/android/app/google-services.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "project_info": { - "project_number": "472301904711", - "firebase_url": "https://epilyon-14f49.firebaseio.com", - "project_id": "epilyon-14f49", - "storage_bucket": "epilyon-14f49.appspot.com" - }, - "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:472301904711:android:14429913ea600fe69f6262", - "android_client_info": { - "package_name": "com.litarvan.epilyon" - } - }, - "oauth_client": [ - { - "client_id": "472301904711-bkhljcv0go6qbl39ofj19h8li6qi4l49.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyAE6jG69NC04GpdDNAAeYSJ94Es5SeNxT8" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "472301904711-bkhljcv0go6qbl39ofj19h8li6qi4l49.apps.googleusercontent.com", - "client_type": 3 - } - ] - } - } - } - ], - "configuration_version": "1" -} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 8309399..a40b58c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ android:label="Epilyon" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round"> + diff --git a/android/app/src/main/kotlin/com/litarvan/epilyon/Application.kt b/android/app/src/main/kotlin/com/litarvan/epilyon/Application.kt index e17ddb5..66d65aa 100644 --- a/android/app/src/main/kotlin/com/litarvan/epilyon/Application.kt +++ b/android/app/src/main/kotlin/com/litarvan/epilyon/Application.kt @@ -1,20 +1,11 @@ package com.litarvan.epilyon import io.flutter.app.FlutterApplication -import io.flutter.plugin.common.PluginRegistry -import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback -import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService -class Application : FlutterApplication(), PluginRegistrantCallback +class Application : FlutterApplication() { override fun onCreate() { super.onCreate() - FlutterFirebaseMessagingService.setPluginRegistrant(this) - } - - override fun registerWith(registry: PluginRegistry?) - { - registry?.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"); } } \ No newline at end of file diff --git a/assets/images/default_thumb.jpg b/assets/images/default_thumb.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bffb38c463c267a5a22d225e016147f44f48001a GIT binary patch literal 3073 zcma)72~-o;8oo0bh6Gsxk!qpX5efQ~tUw?UG_t*FjAgNc1vMcAO(6*+Q36&?T3fK+f|+W~S{8@T=d;*c7MIH)EEw8+l}@T>sI;@5A;ieFGL0ffr%f->hh>|dVM9}LCf|81&N+7G}1tJNjSU-11)VD0k!962jdu2rws z$mE3iEW2}#AX+1r>eQO$YIXLrQ;c7y)~U7Y)HzsmQYe#yiKQ}y$}Vwuh{b}%Dy>ec zlF1jxMEVmLOobvt5YCI^hVj_pY)*JAhZ7sTh!+#LC^jx6lp7Np#*PVo<{P7ytyjub zx@W!_FMRng^|cp+GKYv9BiAT4$TQ+JY9;2_v_SE4F1(lGP5NfMoJ-hCeOUwo+)G$ zB~Nj6ahc-c;!1UO463WU2i3#fl}4L7l}3Bb*Vp&8*Pjo_+1c66)onVJI^D-+}K)kSBmWA(AI#`v&9zKmsHPdU5{&1S3u;i46ToXxBqj07EbdLCGlO zG~ocjo}`(G6K7F^mo(S->26y6S^ubX%`CK?oA_Dq)FXF>Mw4Fg{3E)<&(;fENf5z; z0rF=5`qa$_hd;JKF4 zq`C6-y|nVJ`i`nr;qj(J*Nb%b@(1t=QkM<kZAz^ietVG@}>=M*zh5u4uE9)RwM|Mw?_eI5Hp@~YZS z7U1VrSvK5%JaW1_E#pQ4VZQ2sHT#EM7y9X^m!-1VYb=%`x>#W7m!Gua0Ur92CgEyz^*a+F5+h+mi<0 zF1}b@Qr@uM%9yP`BD?2IkOVRI*3*F6q^KD-N?XqKbWkPr$9LRTVRiJH^wR z2_h+8H;_7>!xYGFO!I5qo}Ts2)_uLT&OY%DsX>SVs^8|QpPP#6!y1l<-ooF%Qb(_& z9~-3C1-|KSptpj{4nyeU1N*OkzN2hZsBsjfizyHW5S!|^y5y~ztJd~MM_g-0As*65 zO!E#QwU@Nc;pbecvR0H>vfdpEX#UlCsy!;3N=9G_MmxODuXIIULrH`BU93#W!5Z<> zJ8&v7Q>fR!cALnEt9x{EXKQ1@aAH;9YXHowqgw_=5)nz|pa4*`ey*E|K8SMNtWu&%7md~L0H%oMhg!J1b*W@;L_ z-NLYZLFV?sYy5CgFVcvA%qFsHF~#QH{t@XgS|&rQc8;V9t(gtq|Ko$7szy$4Y#d$F zBJr_-rx8#3vsv>B631G`pvtmKU){Vgek`rBMSFR)2Td<&*@o6M|1AKS&uhC`xOq8T zJfsS5aJo!oANA?3%xp{k{P=);Suw9OeZ10#eH=R?d^q=)GIUPR9%dP@(* z$ROJP?4`$kTYFHXs|;$cHu%jufEB%R3OFwT0ROzJlv{=jXhL+gm6MgloNi#NMD7gNRml3=oH;gHvd;4St*U-dDDLu;4uuUrLetErKDQ z^DgPrDU|^hkaJTS1>h8-@q6{Sm_(AfMohHPP(+hN6I{w#-J8#k^L|emC;LL&_w$|O z?McWV*b?NNVShZ>N$i+tj`lO;Ar@00UTzGc5Htp9Ca*Ebx-zTNeE0AoC!KQ6 Msu=XnLfhs40H8ogbN~PV literal 0 HcmV?d00001 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 58e65f9..f2872cf 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -1,26 +1,26 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 8.0 - - + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig index 0b2d479..dfd2626 100644 --- a/ios/Flutter/Debug.xcconfig +++ b/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig index 0b2d479..a97381a 100644 --- a/ios/Flutter/Release.xcconfig +++ b/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..9411102 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '10.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..d48d56b --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,143 @@ +PODS: + - Firebase/CoreOnly (8.9.0): + - FirebaseCore (= 8.9.0) + - Firebase/Messaging (8.9.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 8.9.0) + - firebase_core (1.10.0): + - Firebase/CoreOnly (= 8.9.0) + - Flutter + - firebase_messaging (11.1.0): + - Firebase/Messaging (= 8.9.0) + - firebase_core + - Flutter + - FirebaseCore (8.9.0): + - FirebaseCoreDiagnostics (~> 8.0) + - GoogleUtilities/Environment (~> 7.6) + - GoogleUtilities/Logger (~> 7.6) + - FirebaseCoreDiagnostics (8.9.0): + - GoogleDataTransport (~> 9.1) + - GoogleUtilities/Environment (~> 7.6) + - GoogleUtilities/Logger (~> 7.6) + - nanopb (~> 2.30908.0) + - FirebaseInstallations (8.9.0): + - FirebaseCore (~> 8.0) + - GoogleUtilities/Environment (~> 7.6) + - GoogleUtilities/UserDefaults (~> 7.6) + - PromisesObjC (< 3.0, >= 1.2) + - FirebaseMessaging (8.9.0): + - FirebaseCore (~> 8.0) + - FirebaseInstallations (~> 8.0) + - GoogleDataTransport (~> 9.1) + - GoogleUtilities/AppDelegateSwizzler (~> 7.6) + - GoogleUtilities/Environment (~> 7.6) + - GoogleUtilities/Reachability (~> 7.6) + - GoogleUtilities/UserDefaults (~> 7.6) + - nanopb (~> 2.30908.0) + - Flutter (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - GoogleDataTransport (9.1.2): + - GoogleUtilities/Environment (~> 7.2) + - nanopb (~> 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (7.6.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.6.0): + - GoogleUtilities/Environment + - GoogleUtilities/Network (7.6.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.6.0)" + - GoogleUtilities/Reachability (7.6.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (7.6.0): + - GoogleUtilities/Logger + - nanopb (2.30908.0): + - nanopb/decode (= 2.30908.0) + - nanopb/encode (= 2.30908.0) + - nanopb/decode (2.30908.0) + - nanopb/encode (2.30908.0) + - path_provider (0.0.1): + - Flutter + - PromisesObjC (2.0.0) + - shared_preferences (0.0.1): + - Flutter + - sqflite (0.0.2): + - Flutter + - FMDB (>= 2.7.5) + - url_launcher (0.0.1): + - Flutter + - webview_flutter_wkwebview (0.0.1): + - Flutter + +DEPENDENCIES: + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - path_provider (from `.symlinks/plugins/path_provider/ios`) + - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher (from `.symlinks/plugins/url_launcher/ios`) + - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) + +SPEC REPOS: + trunk: + - Firebase + - FirebaseCore + - FirebaseCoreDiagnostics + - FirebaseInstallations + - FirebaseMessaging + - FMDB + - GoogleDataTransport + - GoogleUtilities + - nanopb + - PromisesObjC + +EXTERNAL SOURCES: + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + path_provider: + :path: ".symlinks/plugins/path_provider/ios" + shared_preferences: + :path: ".symlinks/plugins/shared_preferences/ios" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + url_launcher: + :path: ".symlinks/plugins/url_launcher/ios" + webview_flutter_wkwebview: + :path: ".symlinks/plugins/webview_flutter_wkwebview/ios" + +SPEC CHECKSUMS: + Firebase: 13d8d96499e2635428d5bf0ec675df21f95d9a95 + firebase_core: f770e033e790657b3505f04be4cb24c482912f11 + firebase_messaging: 0c8d1a1732487db7f332fb65232053e93201e2fb + FirebaseCore: 599ee609343eaf4941bd188f85e3aa077ffe325b + FirebaseCoreDiagnostics: 5daa63f1c1409d981a2d5007daa100b36eac6a34 + FirebaseInstallations: caa7c8e0d3e2345b8829d2fa9ca1b4dfbf2fcc85 + FirebaseMessaging: 82c4a48638f53f7b184f3cc9f6cd2cbe533ab316 + Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940 + GoogleUtilities: 684ee790a24f73ebb2d1d966e9711c203f2a4237 + nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 + path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de + PromisesObjC: 68159ce6952d93e17b2dfe273b8c40907db5ba58 + shared_preferences: 5033afbb22d372e15aff8ff766df9021b845f273 + sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + url_launcher: b6e016d912f04be9f5bf6e8e82dc599b7ba59649 + webview_flutter_wkwebview: 02b129c6fe415e58e4ab7346512c8c2f79f678db + +PODFILE CHECKSUM: fe0e1ee7f3d1f7d00b11b474b62dd62134535aea + +COCOAPODS: 1.11.0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 4612478..19299c3 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -1,518 +1,605 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - 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 */; }; - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 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 */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, - 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, - ); - 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 = ""; }; - 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; 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 = ""; }; - 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; 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 = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, - 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B80C3931E831B6300D905FE /* App.framework */, - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEBA1CF902C7004384FC /* Flutter.framework */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 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 = 1020; - ORGANIZATIONNAME = "The Chromium Authors"; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 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; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - 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 */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase 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; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - 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 = 8.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; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.litarvan.epilyon; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - 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 = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - 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 = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - 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; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.litarvan.epilyon; - 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; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.litarvan.epilyon; - 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 */ - 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 */; -} +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 14121EA51EA93C0E195A30CC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602A02BF9221D3407A0F22C /* Pods_Runner.framework */; }; + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 383E33EF275A3E11004EEC72 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 383E33EE275A3E11004EEC72 /* GoogleService-Info.plist */; }; + 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 */; }; +/* End PBXBuildFile 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 */ + 10E7B32EE6FCC01E45E56D48 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 383E33EE275A3E11004EEC72 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5C48FAA407724DADA1BC4BC3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 6EE1D0363068070E1DAF3CA7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; 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 = ""; }; + 9602A02BF9221D3407A0F22C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 14121EA51EA93C0E195A30CC /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 34C42320348B4BF8C6591FBD /* Frameworks */ = { + isa = PBXGroup; + children = ( + 9602A02BF9221D3407A0F22C /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 62368B57C08185A39A4A6C52 /* Pods */ = { + isa = PBXGroup; + children = ( + 5C48FAA407724DADA1BC4BC3 /* Pods-Runner.debug.xcconfig */, + 6EE1D0363068070E1DAF3CA7 /* Pods-Runner.release.xcconfig */, + 10E7B32EE6FCC01E45E56D48 /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 62368B57C08185A39A4A6C52 /* Pods */, + 34C42320348B4BF8C6591FBD /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 383E33EE275A3E11004EEC72 /* GoogleService-Info.plist */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 0D2F6C28B6EA39F0238BEA8F /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + C45E1A5CCF722E006A85078C /* [CP] Embed Pods Frameworks */, + ); + 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 = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = PXA86Z77TA; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 383E33EF275A3E11004EEC72 /* GoogleService-Info.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 0D2F6C28B6EA39F0238BEA8F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + 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; + 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"; + }; + C45E1A5CCF722E006A85078C /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseCoreDiagnostics/FirebaseCoreDiagnostics.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", + "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", + "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", + "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", + "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", + "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", + "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework", + "${BUILT_PRODUCTS_DIR}/shared_preferences/shared_preferences.framework", + "${BUILT_PRODUCTS_DIR}/sqflite/sqflite.framework", + "${BUILT_PRODUCTS_DIR}/url_launcher/url_launcher.framework", + "${BUILT_PRODUCTS_DIR}/webview_flutter_wkwebview/webview_flutter_wkwebview.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreDiagnostics.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/shared_preferences.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/sqflite.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/url_launcher.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/webview_flutter_wkwebview.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase 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 = 9.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)"; + DEVELOPMENT_TEAM = PXA86Z77TA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.krax.epilyon; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + 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 = 9.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 = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + 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)"; + DEVELOPMENT_TEAM = PXA86Z77TA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.krax.epilyon; + 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)"; + DEVELOPMENT_TEAM = PXA86Z77TA; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.krax.epilyon; + 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 */ + 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 index 59c6d39..919434a 100644 --- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata index 59c6d39..21a3cc1 100644 --- a/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -1,7 +1,10 @@ - - - - - + + + + + + + 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/Info.plist b/ios/Runner/Info.plist index d8c97fa..8d9c6fe 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,45 +1,45 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - epilyon - 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 - - - + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + epilyon + 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 + + + diff --git a/lib/api_url.dart b/lib/api_url.dart index 91a68d7..d4e6c1f 100644 --- a/lib/api_url.dart +++ b/lib/api_url.dart @@ -1,3 +1,5 @@ // The point of this file is to be edited in local // This is the simplest way to do it, just don't push your changes of this file to git -const API_URL = 'https://api.epilyon.litarvan.com'; \ No newline at end of file +// IOS Emulator: localhost:7899 +// Android Emulator: 10.0.2.2 +const API_URL = 'https://epilyon.krax.fr'; diff --git a/lib/auth.dart b/lib/auth.dart index aafc327..c8a37ed 100644 --- a/lib/auth.dart +++ b/lib/auth.dart @@ -25,11 +25,10 @@ import 'package:epilyon/api.dart'; import 'package:epilyon/firebase.dart'; String _token = ""; -User _user; +User? _user; bool _logged = false; -class User -{ +class User { String username; String firstName; String lastName; @@ -37,24 +36,18 @@ class User String promo; String avatar; - User( - this.username, - this.firstName, - this.lastName, - this.email, - this.promo, - this.avatar - ); + User(this.username, this.firstName, this.lastName, this.email, this.promo, + this.avatar); } -Future canRefresh() async -{ +Future canRefresh() async { final prefs = await SharedPreferences.getInstance(); - return !_logged && prefs.getString('token') != null && prefs.containsKey("user"); + return !_logged && + prefs.getString('token') != null && + prefs.containsKey("user"); } -Future refresh() async -{ +Future refresh() async { final prefs = await SharedPreferences.getInstance(); var token = prefs.getString('token'); if (token == null) { @@ -63,9 +56,8 @@ Future refresh() async print('Loading token : ' + token); - var result = await http.post(API_URL + '/auth/refresh', headers: { - 'Token': token - }); + var result = await http + .post(Uri.parse(API_URL + '/auth/refresh'), headers: {'Token': token}); var json; try { @@ -82,21 +74,18 @@ Future refresh() async return true; } -Future createSession() async -{ +Future createSession() async { var deviceToken = await getDeviceToken(); - var result = await http.post(API_URL + '/auth/start', headers: { - 'Content-Type': 'application/json' - }, body: '{"device_token": "$deviceToken"}'); + var result = await http.post(Uri.parse(API_URL + '/auth/start'), + headers: {'Content-Type': 'application/json'}, + body: '{"device_token": "$deviceToken"}'); _token = parseResponse(result.body)['token']; } -Future login() async -{ - var result = await http.post(API_URL + '/auth/end', headers: { - 'Token': getToken() - }); +Future login() async { + var result = await http + .post(Uri.parse(API_URL + '/auth/end'), headers: {'Token': getToken()!}); var json = parseResponse(result.body); await setUser(json['user']); @@ -105,8 +94,7 @@ Future login() async return json['first_time']; } -Future cancelLogin() async -{ +Future cancelLogin() async { _token = ''; _user = null; _logged = false; @@ -115,29 +103,20 @@ Future cancelLogin() async prefs.remove('token'); } -Future setUser(dynamic user) async -{ +Future setUser(dynamic user) async { final prefs = await SharedPreferences.getInstance(); prefs.setString('token', _token); print('Saving token : ' + _token); - _user = User( - user['username'], - user['first_name'], - user['last_name'], - user['email'], - user['promo'], - user['avatar'] - ); + _user = User(user['username'], user['first_name'], user['last_name'], + user['email'], user['promo'], user['avatar']); - print("Logged in as '" + _user.firstName + " " + _user.lastName + "'"); + print("Logged in as '" + _user!.firstName + " " + _user!.lastName + "'"); } -Future logout() async -{ - var result = await http.post(API_URL + '/auth/logout', headers: { - 'Token': getToken() - }); +Future logout() async { + var result = await http.post(Uri.parse(API_URL + '/auth/logout'), + headers: {'Token': getToken()!}); parseResponse(result.body); @@ -149,41 +128,61 @@ Future logout() async prefs.remove('token'); } -Future loadUser() async -{ +Future loadUser() async { final prefs = await SharedPreferences.getInstance(); - if (!prefs.containsKey('user')) { + if (!prefs.containsKey('user') || !prefs.containsKey("token")) { return; } - _token = prefs.getString("token"); - setUser(jsonDecode(prefs.getString('user'))); + _token = prefs.getString('token')!; + setUser(jsonDecode(prefs.getString('user')!)); } -Future saveUser() async -{ +Future saveUser() async { final prefs = await SharedPreferences.getInstance(); - prefs.setString("user", jsonEncode({ - 'username': _user.username, - 'first_name': _user.firstName, - 'last_name': _user.lastName, - 'email': _user.email, - 'promo': _user.promo, - 'avatar': _user.avatar - })); + prefs.setString( + "user", + jsonEncode({ + 'username': _user!.username, + 'first_name': _user!.firstName, + 'last_name': _user!.lastName, + 'email': _user!.email, + 'promo': _user!.promo, + 'avatar': _user!.avatar + })); } -bool isLogged() -{ +int getYearAtEpita() { + var now = DateTime.now(); + var semesterOffset = now.month > 7 ? 0 : 1; + return 5 - int.parse("2026") + now.year + semesterOffset; +} + +String getPromoName() { + switch (getYearAtEpita()) { + case 0: + return "SUP"; + case 1: + return "SPE"; + case 2: + return "ING1"; + case 3: + return "ING2"; + case 4: + return "ING3"; + default: + return "BRO"; + } +} + +bool isLogged() { return _logged; } -String getToken() -{ +String? getToken() { return _token; } -User getUser() -{ +User? getUser() { return _user; } diff --git a/lib/data.dart b/lib/data.dart index 3af1f16..3560acc 100644 --- a/lib/data.dart +++ b/lib/data.dart @@ -27,106 +27,122 @@ import 'package:epilyon/auth.dart'; import 'package:epilyon/delegates.dart'; import 'package:epilyon/mimos.dart'; import 'package:epilyon/mcq.dart'; - -class UserData -{ - Delegate admin; - List delegates; - List mcqHistory; - List mimos; - NextMCQ nextMcq; - - UserData({ this.admin, this.delegates, this.mcqHistory, this.mimos, this.nextMcq }); +import 'package:epilyon/task.dart'; + +class UserData { + Delegate? admin; + List? delegates; + List? mcqHistory; + List? mimos; + NextMCQ? nextMcq; + List? tasks; + + UserData( + {this.admin, + this.delegates, + this.mcqHistory, + this.mimos, + this.nextMcq, + this.tasks}); } -UserData data; +late UserData data; -DateFormat mcqDateFormat = new DateFormat('yyyy-MM-dd'); +DateFormat jsonDateFormat = new DateFormat('yyyy-MM-dd'); DateFormat mimosDateFormat = new DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); Future testConnection() async { - await http.get('http://google.com/'); + await http.get(Uri.parse('http://google.com/')); } Future pingServer() async { - await http.get(API_URL + '/'); + await http.get(Uri.parse(API_URL + '/')); } Future fetchData() async { - var result = await http.get(API_URL + '/data/get', headers: { - 'Token': getToken() - }); + var result = await http + .get(Uri.parse(API_URL + '/data/get'), headers: {'Token': getToken()!}); data = parseData(parseResponse(utf8.decode(result.bodyBytes))['data']); await save(); } Future forceRefresh() async { - var result = await http.post(API_URL + '/data/refresh', headers: { - 'Token': getToken() - }); + var result = await http.post(Uri.parse(API_URL + '/data/refresh'), + headers: {'Token': getToken()!}); parseResponse(result.body); } // TODO: Rework this part SOON -UserData parseData(dynamic data) -{ - List delegates = data['delegates'].map((delegate) { +UserData parseData(dynamic data) { + List? delegates = data['delegates'].map((delegate) { return Delegate(delegate['name'], delegate['email']); }).toList(); List mcqs = data['mcq_history'].map((mcq) { - List grades = mcq['grades'].map((grade) => MCQGrade( - grade['subject'], - grade['points'] - .map((p) => p as double) - .toList() - .reduce((a, b) => a + b) - )).toList(); - - return MCQ( - mcqDateFormat.parse(mcq['date']), - mcq['average'], - grades - ); + List? grades = mcq['grades'] + .map((grade) => MCQGrade( + grade['subject'], + grade['points'] + .map((p) => p as double) + .toList() + .reduce((a, b) => a + b))) + .toList(); + + return MCQ(jsonDateFormat.parse(mcq['date']), mcq['average'], grades); }).toList(); mcqs.sort((a, b) => -a.date.compareTo(b.date)); - List mimos = data['mimos'].map((mimos) => Mimos( - mimos['subject'], - mimos['number'], - mimos['title'], - mimosDateFormat.parse(mimos['date']) - )).toList(); + List? mimos = data['mimos'] + .map((mimos) => Mimos(mimos['subject'], mimos['number'], + mimos['title'], mimosDateFormat.parse(mimos['date']))) + .toList(); var next = data['next_mcq']; - NextMCQ nextMcq; + NextMCQ? nextMcq; if (next != null) { nextMcq = NextMCQ( next['skipped'], mimosDateFormat.parse(next['at']), - next['revisions'].map((revision) => MCQRevision( - revision['subject'], - revision['work'].map((s) => s as String).toList() - )).toList(), - next['last_editor'] - ); + next['revisions'] + .map((revision) => MCQRevision(revision['subject'], + revision['work'].map((s) => s as String).toList())) + .toList(), + next['last_editor']); } + List? tasks = data['tasks'] + .map((task) => Task( + jsonDateFormat.parse(task['created_at']), + jsonDateFormat.parse(task['updated_at']), + task['short_id'], + task['visibility'], + task['promotion'], + task['semester'], + task['region'], + task['title'], + task['subject'], + task['content'], + jsonDateFormat.parse(task['due_date']), + task['created_by_login'], + task['created_by'], + task['updated_by_login'], + task['updated_by'])) + .toList(); + return UserData( admin: Delegate(data['admin']['name'], data['admin']['email']), delegates: delegates, mcqHistory: mcqs, mimos: mimos, - nextMcq: nextMcq - ); + nextMcq: nextMcq, + tasks: tasks); } -Future load() async -{ +Future load() async { await loadUser(); final prefs = await SharedPreferences.getInstance(); @@ -135,110 +151,157 @@ Future load() async var delegates = []; var mcqs = []; var mimos = []; + var tasks = []; NextMCQ nextMcq; if (prefs.containsKey('admin')) { - var json = jsonDecode(prefs.getString('admin')); + var json = jsonDecode(prefs.getString('admin')!); admin = Delegate(json['name'], json['email']); } if (prefs.containsKey('delegates')) { - for (var delegate in prefs.getStringList('delegates')) { + for (var delegate in prefs.getStringList('delegates')!) { var json = jsonDecode(delegate); delegates.add(Delegate(json['name'], json['email'])); } } if (prefs.containsKey('mcqs')) { - for (var mcq in prefs.getStringList('mcqs')) { + for (var mcq in prefs.getStringList('mcqs')!) { var json = jsonDecode(mcq); mcqs.add(MCQ( DateTime.fromMicrosecondsSinceEpoch(json['date']), json['average'], - json['grades'].map((g) => MCQGrade(g['subject'], g['grade'])).toList() - )); + json['grades'] + .map((g) => MCQGrade(g['subject'], g['grade'])) + .toList())); + } + } + + if (prefs.containsKey('tasks')) { + for (var task in prefs.getStringList('tasks')!) { + var json = jsonDecode(task); + + tasks.add(Task( + jsonDateFormat.parse(json['created_at']), + jsonDateFormat.parse(json['updated_at']), + json['short_id'], + json['visibility'], + json['promotion'], + json['semester'], + json['region'], + json['title'], + json['subject'], + json['content'], + jsonDateFormat.parse(json['due_date']), + json['created_by_login'], + json['created_by'], + json['updated_by_login'], + json['updated_by'])); } } if (prefs.containsKey('mimos')) { - for (var m in prefs.getStringList('mimos')) { + for (var m in prefs.getStringList('mimos')!) { var json = jsonDecode(m); - mimos.add(Mimos( - json['subject'], - json['number'], - json['title'], - mimosDateFormat.parse(json['date']) - )); + mimos.add(Mimos(json['subject'], json['number'], json['title'], + mimosDateFormat.parse(json['date']))); } } if (prefs.containsKey('nextMcq')) { - var json = jsonDecode(prefs.getString("nextMcq")); + var json = jsonDecode(prefs.getString("nextMcq")!); if (json != null) { nextMcq = NextMCQ( json['skipped'], mimosDateFormat.parse(json['at']), - json['revisions'].map((r) => MCQRevision( - r['subject'], - r['work'].map((s) => s as String).toList() - )).toList(), - json['lastEditor'] - ); + json['revisions'] + .map((r) => MCQRevision(r['subject'], + r['work'].map((s) => s as String).toList())) + .toList(), + json['lastEditor']); } } data = UserData( - admin: admin, - delegates: delegates, - mcqHistory: mcqs, - mimos: mimos - ); + admin: admin, delegates: delegates, mcqHistory: mcqs, mimos: mimos); } -Future save() async -{ +Future save() async { await saveUser(); final prefs = await SharedPreferences.getInstance(); - prefs.setString("admin", jsonEncode({ 'name': data.admin.name, 'email': data.admin.email })); - - prefs.setStringList('delegates', data.delegates.map((delegate) => jsonEncode({ - 'name': delegate.name, - 'email': delegate.email - })).toList()); - - prefs.setStringList('mcqs', data.mcqHistory.map((mcq) => jsonEncode({ - 'date': mcq.date.microsecondsSinceEpoch, - 'average': mcq.average, - 'grades': mcq.grades.map((grade) => { - 'subject': grade.subject, - 'grade': grade.grade - }).toList() - })).toList()); - - prefs.setStringList('mimos', data.mimos.map((mimos) => jsonEncode({ - 'subject': mimos.subject, - 'number': mimos.number, - 'title': mimos.title, - 'date': mimosDateFormat.format(mimos.date) - })).toList()); - - Map next; + prefs.setString("admin", + jsonEncode({'name': data.admin!.name, 'email': data.admin!.email})); + + prefs.setStringList( + 'delegates', + data.delegates! + .map((delegate) => + jsonEncode({'name': delegate.name, 'email': delegate.email})) + .toList()); + + prefs.setStringList( + 'mcqs', + data.mcqHistory! + .map((mcq) => jsonEncode({ + 'date': mcq.date.microsecondsSinceEpoch, + 'average': mcq.average, + 'grades': mcq.grades! + .map((grade) => + {'subject': grade.subject, 'grade': grade.grade}) + .toList() + })) + .toList()); + + prefs.setStringList( + 'tasks', + data.tasks! + .map((task) => jsonEncode({ + 'created_at': jsonDateFormat.format(task.createdAt!), + 'updated_at': jsonDateFormat.format(task.updatedAt!), + 'short_id': task.shortId, + 'visibility': task.visibility, + 'promotion': task.promotion, + 'semester': task.semester, + 'region': task.region, + 'title': task.title, + 'subject': task.subject, + 'content': task.content, + 'due_date': jsonDateFormat.format(task.dueDate!), + 'created_by_login': task.createdByLogin, + 'created_by': task.createdBy, + 'updated_by_login': task.updatedBy, + 'updated_by': task.updatedByLogin + })) + .toList()); + + prefs.setStringList( + 'mimos', + data.mimos! + .map((mimos) => jsonEncode({ + 'subject': mimos.subject, + 'number': mimos.number, + 'title': mimos.title, + 'date': mimosDateFormat.format(mimos.date!) + })) + .toList()); + + Map? next; if (data.nextMcq != null) { next = { - 'skipped': data.nextMcq.skipped, - 'at': mimosDateFormat.format(data.nextMcq.at), - 'revisions': data.nextMcq.revisions.map((r) => { - 'subject': r.subject, - 'work': r.work - }).toList(), - 'lastEditor': data.nextMcq.lastEditor + 'skipped': data.nextMcq!.skipped, + 'at': mimosDateFormat.format(data.nextMcq!.at), + 'revisions': data.nextMcq!.revisions! + .map((r) => {'subject': r.subject, 'work': r.work}) + .toList(), + 'lastEditor': data.nextMcq!.lastEditor }; } prefs.setString("nextMcq", jsonEncode(next)); -} \ No newline at end of file +} diff --git a/lib/delegates.dart b/lib/delegates.dart index 8efdf3e..b3de4e8 100644 --- a/lib/delegates.dart +++ b/lib/delegates.dart @@ -24,55 +24,46 @@ import 'package:epilyon/api_url.dart'; import 'package:epilyon/auth.dart'; import 'package:epilyon/data.dart'; -Delegate get admin => data.admin; -List get delegates => data.delegates; +Delegate? get admin => data.admin; +List? get delegates => data.delegates; -bool isUserAdmin() -{ - return data.admin.email == getUser().email; +bool isUserAdmin() { + return data.admin!.email == getUser()!.email; } -bool isUserDelegate() -{ - return data.delegates.any((del) => del.email == getUser().email); +bool isUserClassRep() { + return data.delegates!.any((del) => del.email == getUser()!.email); } -Future addDelegate(String email) async -{ - var result = await http.post(API_URL + '/delegates/add', headers: { - 'Content-Type': 'application/json', - 'Token': getToken() - }, body: jsonEncode({ 'email': email })); +Future addDelegate(String email) async { + var result = await http.post(Uri.parse(API_URL + '/delegates/add'), + headers: {'Content-Type': 'application/json', 'Token': getToken()!}, + body: jsonEncode({'email': email})); return parseResponse(utf8.decode(result.bodyBytes))['name']; } -Future removeDelegate(String email) async -{ - var result = await http.post(API_URL + '/delegates/remove', headers: { - 'Content-Type': 'application/json', - 'Token': getToken() - }, body: jsonEncode({ 'email': email })); +Future removeDelegate(String? email) async { + var result = await http.post(Uri.parse(API_URL + '/delegates/remove'), + headers: {'Content-Type': 'application/json', 'Token': getToken()!}, + body: jsonEncode({'email': email})); parseResponse(utf8.decode(result.bodyBytes)); } -Future notifyAll(String text) async -{ - print('aaa' + getToken()); - var result = await http.post(API_URL + '/delegates/notify', headers: { - 'Content-Type': 'application/json', - 'Token': getToken() - }, body: jsonEncode({ 'content': text })); +Future notifyAll(String text) async { + print('aaa' + getToken()!); + var result = await http.post(Uri.parse(API_URL + '/delegates/notify'), + headers: {'Content-Type': 'application/json', 'Token': getToken()!}, + body: jsonEncode({'content': text})); print('ooo' + result.body); parseResponse(utf8.decode(result.bodyBytes)); } -class Delegate -{ - String name; - String email; +class Delegate { + String? name; + String? email; Delegate(this.name, this.email); -} \ No newline at end of file +} diff --git a/lib/firebase.dart b/lib/firebase.dart index 074cdc5..6d7b271 100644 --- a/lib/firebase.dart +++ b/lib/firebase.dart @@ -1,55 +1,38 @@ import 'package:firebase_messaging/firebase_messaging.dart'; -final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); +final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance; // TODO: Impl this and open right view depending on notification bool _initialized = false; -void initFirebase() -{ +void initFirebase() { if (_initialized) { return; } _initialized = true; - _firebaseMessaging.configure( - onMessage: (Map message) async { - // {notification: {title: this is a title, body: this is a body}, data: {status: done, id: 1, color: #ff0000, click_action: FLUTTER_NOTIFICATION_CLICK}} - print("onMessage: $message"); - }, - onBackgroundMessage: handleBackgroundMessage, - onLaunch: (Map message) async { - print("onLaunch: $message"); - }, - onResume: (Map message) async { - // {notification: {}, data: {collapse_key: com.litarvan.epilyon, color: #ff0000, google.original_priority: high, google.sent_time: 1581341404242, google.delivered_priority: high, google.ttl: 2419200, from: 472301904711, id: 1, click_action: FLUTTER_NOTIFICATION_CLICK, google.message_id: 0:1581341404252844%4fecd5444fecd544, status: done}} - print("onResume: $message"); - }, - ); + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // {notification: {title: this is a title, body: this is a body}, data: {status: done, id: 1, color: #ff0000, click_action: FLUTTER_NOTIFICATION_CLICK}} + print("onMessage: $message"); + }); + FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage); } -Future handleBackgroundMessage(Map message) async { - if (message.containsKey('data')) { - // Handle data message - final dynamic data = message['data']; - print('Data : '); - print(data); - } +Future handleBackgroundMessage(RemoteMessage message) async { + // Handle data message + print('Data : '); + print(message.data); - if (message.containsKey('notification')) { - // Handle notification message - final dynamic notification = message['notification']; - print('Notification : '); - print(notification); - } + print('Notification : '); + print(message.notification); // Or do other work. return ""; } -Future getDeviceToken() async { +Future getDeviceToken() async { try { return await _firebaseMessaging.getToken(); } catch (e) { diff --git a/lib/main.dart b/lib/main.dart index ed526fc..733745c 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,6 +17,7 @@ */ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:epilyon/data.dart'; @@ -26,25 +27,24 @@ import 'package:epilyon/pages/main.dart'; const VERSION = 'v0.1.0'; -void main() -{ +void main() { initializeDateFormatting('fr_FR'); WidgetsFlutterBinding.ensureInitialized(); + load().then((_) async { + await Firebase.initializeApp(); runApp(MyApp(await canRefresh())); }); } -class MyApp extends StatelessWidget -{ +class MyApp extends StatelessWidget { final bool canRefresh; MyApp(this.canRefresh); @override - Widget build(BuildContext context) - { + Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, @@ -53,17 +53,17 @@ class MyApp extends StatelessWidget return MaterialApp( title: 'Epilyon', theme: ThemeData( - // TODO: Custom theming - primaryColor: Color(0xFF027CFF), // 0xFF8643e6 - canvasColor: Color(0xFFF5F7F9), - fontFamily: 'Roboto', - appBarTheme: AppBarTheme( - textTheme: TextTheme( - headline6: TextStyle(fontFamily: 'LatoE', fontSize: 19, fontWeight: FontWeight.w600) - ), - elevation: 0 - ) - ), + // TODO: Custom theming + primaryColor: Color(0xFF027CFF), // 0xFF8643e6 + canvasColor: Color(0xFFF5F7F9), + fontFamily: 'Roboto', + appBarTheme: AppBarTheme( + textTheme: TextTheme( + headline6: TextStyle( + fontFamily: 'LatoE', + fontSize: 19, + fontWeight: FontWeight.w600)), + elevation: 0)), home: canRefresh ? MainPage() : LoginPage(), ); } diff --git a/lib/mcq.dart b/lib/mcq.dart index 9bb650e..4e71bfe 100644 --- a/lib/mcq.dart +++ b/lib/mcq.dart @@ -15,37 +15,33 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -class MCQ -{ +class MCQ { DateTime date; - double average; - List grades; + double? average; + List? grades; MCQ(this.date, this.average, this.grades); } -class MCQGrade -{ - String subject; - double grade; +class MCQGrade { + String? subject; + double? grade; MCQGrade(this.subject, this.grade); } -class NextMCQ -{ - bool skipped; +class NextMCQ { + bool? skipped; DateTime at; - List revisions; - String lastEditor; + List? revisions; + String? lastEditor; NextMCQ(this.skipped, this.at, this.revisions, this.lastEditor); } -class MCQRevision -{ - String subject; - List work; +class MCQRevision { + String? subject; + List? work; MCQRevision(this.subject, this.work); } diff --git a/lib/mimos.dart b/lib/mimos.dart index 622dbb8..1e9dd7a 100644 --- a/lib/mimos.dart +++ b/lib/mimos.dart @@ -24,43 +24,35 @@ import 'package:epilyon/api_url.dart'; import 'package:epilyon/auth.dart'; import 'package:epilyon/data.dart'; -List get mimos => data.mimos; - -Future addMimos(Mimos mimos) async -{ - print(mimosDateFormat.format(mimos.date)); - var result = await http.post(API_URL + '/mimos/add', headers: { - 'Content-Type': 'application/json', - 'Token': getToken() - }, body: jsonEncode({ - 'subject': mimos.subject, - 'number': mimos.number, - 'title': mimos.title, - 'date': mimosDateFormat.format(mimos.date) - })); +List? get mimos => data.mimos; + +Future addMimos(Mimos mimos) async { + print(mimosDateFormat.format(mimos.date!)); + var result = await http.post(Uri.parse(API_URL + '/mimos/add'), + headers: {'Content-Type': 'application/json', 'Token': getToken()!}, + body: jsonEncode({ + 'subject': mimos.subject, + 'number': mimos.number, + 'title': mimos.title, + 'date': mimosDateFormat.format(mimos.date!) + })); parseResponse(utf8.decode(result.bodyBytes)); } -Future removeMimos(String subject, int number) async -{ - var result = await http.post(API_URL + '/mimos/remove', headers: { - 'Content-Type': 'application/json', - 'Token': getToken() - }, body: jsonEncode({ - 'subject': subject, - 'number': number - })); +Future removeMimos(String? subject, int? number) async { + var result = await http.post(Uri.parse(API_URL + '/mimos/remove'), + headers: {'Content-Type': 'application/json', 'Token': getToken()!}, + body: jsonEncode({'subject': subject, 'number': number})); parseResponse(utf8.decode(result.bodyBytes)); } -class Mimos -{ - String subject; - int number; - String title; - DateTime date; +class Mimos { + String? subject; + int? number; + String? title; + DateTime? date; Mimos(this.subject, this.number, this.title, this.date); -} \ No newline at end of file +} diff --git a/lib/pages.dart b/lib/pages.dart index 40c5df2..716b516 100644 --- a/lib/pages.dart +++ b/lib/pages.dart @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +import 'package:epilyon/pages/task/task_list.dart'; import 'package:flutter/material.dart'; import 'package:epilyon/delegates.dart'; @@ -39,46 +40,37 @@ final List pages = [ title: 'Résultats du Q.C.M.', tabTitle: 'Résultats', icon: 'assets/icons/done_all.svg', - page: MCQResultPage() - ), + page: MCQResultPage()), EpiPage( title: 'Historique des Q.C.M.s', icon: 'assets/icons/list.svg', tabTitle: 'Historique', - page: MCQHistoryPage() - ) - ] - ), - EpiPage( - title: 'MiMos', - icon: 'assets/icons/work.svg', - page: MimosPage() - ), + page: MCQHistoryPage()) + ]), + // EpiPage(title: 'MiMos', icon: 'assets/icons/work.svg', page: MimosPage()), + EpiPage(title: 'Tâches', icon: 'assets/icons/work.svg', page: TaskPage()), EpiPage( - title: 'Gérer', - icon: 'assets/icons/build.svg', - onlyIf: () => isUserAdmin() || isUserDelegate() || false, - tabIndex: 0, - tabs: [ - EpiPage( - title: 'Gestion générale', - tabTitle: 'Général', - icon: 'assets/icons/build.svg', - page: ManagePage() - ), - EpiPage( - title: 'Gestion des MiMos', - tabTitle: 'MiMos', - icon: 'assets/icons/work.svg', - page: MimosPage(canAdd: true, canRemove: true) - ), - EpiPage( - title: 'Gestion des Q.C.M.s', - tabTitle: 'Q.C.M.s', - icon: 'assets/icons/check_box.svg' - ) - ] - ), + title: 'Gérer', + icon: 'assets/icons/build.svg', + onlyIf: () => isUserAdmin() || isUserClassRep() || false, + tabIndex: 0, + tabs: [ + EpiPage( + title: 'Gestion générale', + tabTitle: 'Général', + icon: 'assets/icons/build.svg', + page: ManagePage()), + EpiPage( + title: 'Gestion des MiMos', + tabTitle: 'MiMos', + icon: 'assets/icons/work.svg', + page: MimosPage(canAdd: true, canRemove: true)), + // EpiPage( + // title: 'Gestion des Q.C.M.s', + // tabTitle: 'Q.C.M.s', + // icon: 'assets/icons/check_box.svg' + // ) + ]), EpiPage( title: 'Paramètres', icon: 'assets/icons/settings.svg', @@ -87,36 +79,28 @@ final List pages = [ EpiPage( title: 'Se déconnecter', icon: 'assets/icons/first_page.svg', - action: 'logout' - ), - EpiPage( - title: 'À Propos', - icon: 'assets/icons/info.svg', - page: AboutPage() - ), + action: 'logout'), + EpiPage(title: 'À Propos', icon: 'assets/icons/info.svg', page: AboutPage()), ]; -class EpiPage -{ +class EpiPage { String title; - String tabTitle; + String? tabTitle; String icon; - Widget page; + Widget? page; List tabs; - String action; + String? action; int tabIndex; - bool Function() onlyIf; - - EpiPage({ - @required this.title, - this.tabTitle, - @required this.icon, - this.page, - this.tabs = const [], - this.action, - this.tabIndex = 0, + bool Function()? onlyIf; - this.onlyIf - }); + EpiPage( + {required this.title, + this.tabTitle, + required this.icon, + this.page, + this.tabs = const [], + this.action, + this.tabIndex = 0, + this.onlyIf}); } diff --git a/lib/pages/about.dart b/lib/pages/about.dart index 95178e3..569ece1 100644 --- a/lib/pages/about.dart +++ b/lib/pages/about.dart @@ -25,7 +25,7 @@ import 'package:epilyon/widgets/card.dart'; class AboutPage extends StatefulWidget { - AboutPage({ Key key }) : super(key: key); + AboutPage({ Key? key }) : super(key: key); @override _AboutPageState createState() => _AboutPageState(); diff --git a/lib/pages/base.dart b/lib/pages/base.dart index 833732a..72ed591 100644 --- a/lib/pages/base.dart +++ b/lib/pages/base.dart @@ -26,14 +26,14 @@ double barHeight = 54.0; class BasePage extends StatefulWidget { - final String title; - final Widget drawer; - final Widget bottomNav; + final String? title; + final Widget? drawer; + final Widget? bottomNav; final bool fixed; - final Widget child; + final Widget? child; BasePage({ - Key key, + Key? key, this.title, this.drawer, this.bottomNav, @@ -51,7 +51,7 @@ class _BasePageState extends State Widget build(BuildContext context) { return Scaffold( - appBar: buildAppBar(context, barHeight), + appBar: buildAppBar(context, barHeight) as PreferredSizeWidget?, drawer: widget.drawer, bottomNavigationBar: widget.bottomNav, body: EpiContent( @@ -75,7 +75,7 @@ class _BasePageState extends State ]), child: AppBar( elevation: 0.0, - title: Text(widget.title), + title: Text(widget.title!), titleSpacing: 3.0, actions: widget.drawer == null || !isLogged() ? null : [ RefreshButton() diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 4fd7381..836ee43 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -24,7 +24,7 @@ import 'package:epilyon/pages/ms_login.dart'; class LoginPage extends StatefulWidget { - LoginPage({ Key key }) : super(key: key); + LoginPage({ Key? key }) : super(key: key); @override _LoginPageState createState() => _LoginPageState(); @@ -32,7 +32,7 @@ class LoginPage extends StatefulWidget class _LoginPageState extends State { - BuildContext _dialogContext; + BuildContext? _dialogContext; void _onConnectPress(BuildContext context) { @@ -49,7 +49,7 @@ class _LoginPageState extends State return; } - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); Navigator.push( context, MaterialPageRoute(builder: (context) => MSLoginPage()) @@ -62,7 +62,7 @@ class _LoginPageState extends State print('Error during session creation : ' + e.toString()); print(trace); - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); showErrorDialog( context, title: 'Erreur', diff --git a/lib/pages/main.dart b/lib/pages/main.dart index 299bbea..99ae545 100644 --- a/lib/pages/main.dart +++ b/lib/pages/main.dart @@ -26,123 +26,108 @@ import 'package:epilyon/pages/base.dart'; import 'package:epilyon/pages/login.dart'; import 'package:epilyon/widgets/dialogs.dart'; -void pushMain(BuildContext context) -{ +void pushMain(BuildContext context) { Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => MainPage()) - ); + context, MaterialPageRoute(builder: (context) => MainPage())); } -class MainPage extends StatefulWidget -{ - MainPage({ Key key }) : super(key: key); +class MainPage extends StatefulWidget { + MainPage({Key? key}) : super(key: key); @override _MainPageState createState() => _MainPageState(); } -class _MainPageState extends State -{ +class _MainPageState extends State { // TODO: Page switching animation ? - EpiPage selectedPage; - BuildContext _dialogContext; + EpiPage? selectedPage; + BuildContext? _dialogContext; @override - void initState() - { + void initState() { super.initState(); initFirebase(); selectedPage = getUser() == null ? pages[5] : pages[0]; } - void showLogoutDialog() - { + void showLogoutDialog() { showConfirmDialog(context, title: 'Se déconnecter', content: 'Voulez-vous vraiment vous déconnecter ?', okText: 'Oui', cancelText: 'Non', - onConfirm: () => doLogout() - ); + onConfirm: () => doLogout()); } - void doLogout() - { - showLoadingDialog( - context, + void doLogout() { + showLoadingDialog(context, title: 'Déconnexion', content: 'Déconnexion en cours...', - onContextUpdate: (ctx) => _dialogContext = ctx - ); + onContextUpdate: (ctx) => _dialogContext = ctx); logout().catchError((e, trace) { print('Error while doing logout : ' + e.toString()); print(trace); - showErrorDialog( - context, + showErrorDialog(context, title: 'Erreur', - content: "Erreur lors de la déconnexion : " + e.toString() - ); + content: "Erreur lors de la déconnexion : " + e.toString()); }).whenComplete(() { if (_dialogContext != null) { - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); } Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => LoginPage()) - ); + context, MaterialPageRoute(builder: (context) => LoginPage())); }); } @override - Widget build(BuildContext context) - { + Widget build(BuildContext context) { Color primary = Theme.of(context).primaryColor; - Widget content = selectedPage.tabs.length > 0 - ? selectedPage.tabs[selectedPage.tabIndex].page - : selectedPage.page; + Widget? content = selectedPage!.tabs.length > 0 + ? selectedPage!.tabs[selectedPage!.tabIndex].page + : selectedPage!.page; return WillPopScope( onWillPop: () async => false, child: BasePage( - title: selectedPage.tabs.length > 0 - ? selectedPage.tabs[selectedPage.tabIndex].title - : selectedPage.title, + title: selectedPage!.tabs.length > 0 + ? selectedPage!.tabs[selectedPage!.tabIndex].title + : selectedPage!.title, drawer: buildDrawer(context), - bottomNav: selectedPage.tabs.length > 0 ? BottomNavigationBar( - currentIndex: selectedPage.tabIndex, - elevation: 20.0, - onTap: (tab) => setState(() { - if (selectedPage.tabs[tab].page != null) { - selectedPage.tabIndex = tab; - } - }), - items: selectedPage.tabs.map((page) { - bool selected = content == page.page; + bottomNav: selectedPage!.tabs.length > 0 + ? BottomNavigationBar( + currentIndex: selectedPage!.tabIndex, + elevation: 20.0, + onTap: (tab) => setState(() { + if (selectedPage!.tabs[tab].page != null) { + selectedPage!.tabIndex = tab; + } + }), + items: selectedPage!.tabs.map((page) { + bool selected = content == page.page; - return BottomNavigationBarItem( - icon: SvgPicture.asset( - page.icon, - width: 24, - color: selected ? primary : Color(0xFF999999), - ), // TODO: Better way (color) ? - title: Text(page.tabTitle != null ? page.tabTitle : page.title) - ); - }).toList(), - ) : null, + return BottomNavigationBarItem( + icon: SvgPicture.asset( + page.icon, + width: 24, + color: selected ? primary : Color(0xFF999999), + ), // TODO: Better way (color) ? + title: Text( + page.tabTitle != null ? page.tabTitle! : page.title)); + }).toList(), + ) + : null, child: content, ), ); } - void rebuild() - { - ElementVisitor visitor; + void rebuild() { + late ElementVisitor visitor; visitor = (child) { if (child.widget is MainPage) { child.markNeedsBuild(); @@ -161,20 +146,22 @@ class _MainPageState extends State context.visitChildElements(visitor); } - Widget buildDrawer(BuildContext context) - { + Widget buildDrawer(BuildContext context) { Color primary = Theme.of(context).primaryColor; MediaQueryData media = MediaQuery.of(context); - User user = getUser(); + User user = getUser()!; + String promoName = getPromoName(); return Theme( data: Theme.of(context).copyWith( canvasColor: primary, textTheme: TextTheme( - bodyText1: TextStyle(color: Colors.white, fontFamily: 'LatoE', fontSize: 18, fontWeight: FontWeight.w600) - ) - ), + bodyText1: TextStyle( + color: Colors.white, + fontFamily: 'LatoE', + fontSize: 18, + fontWeight: FontWeight.w600))), child: Drawer( child: ListView( padding: EdgeInsets.zero, @@ -182,36 +169,50 @@ class _MainPageState extends State Theme( data: Theme.of(context).copyWith( textTheme: TextTheme( - bodyText2: TextStyle(color: Colors.black, fontFamily: 'Lato', fontSize: 18) - ) - ), + bodyText2: TextStyle( + color: Colors.black, + fontFamily: 'Lato', + fontSize: 18))), child: Container( - padding: EdgeInsets.only(left: 12.5, top: 12.5 + media.padding.top), + padding: + EdgeInsets.only(left: 12.5, top: 12.5 + media.padding.top), height: 150.0, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - shape: BoxShape.circle, - image: DecorationImage( - image: CachedNetworkImageProvider(user.avatar), - fit: BoxFit.cover, - alignment: Alignment.topCenter - ) - ) - ), + CachedNetworkImage( + imageUrl: user.avatar, + imageBuilder: (context, imageProvider) => Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: imageProvider, + fit: BoxFit.cover), + ), + ), + errorWidget: (context, url, error) => Container( + width: 60, + height: 60, + decoration: BoxDecoration( + shape: BoxShape.circle, + image: DecorationImage( + image: AssetImage( + "assets/images/default_thumb.jpg"), + fit: BoxFit.cover, + alignment: Alignment.topCenter)))), Padding( padding: const EdgeInsets.only(left: 12.5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 0.75), // To compensate the use of italic + padding: const EdgeInsets.only( + left: + 0.75), // To compensate the use of italic child: Row( children: [ Text( @@ -220,31 +221,32 @@ class _MainPageState extends State fontSize: 18.0, fontStyle: FontStyle.italic, fontWeight: FontWeight.normal, - color: Colors.black - ), + color: Colors.black), ), Padding( padding: const EdgeInsets.only(left: 5.0), child: Container( decoration: BoxDecoration( color: Colors.black, - borderRadius: BorderRadius.all(Radius.circular(3.0)) - ), + borderRadius: BorderRadius.all( + Radius.circular(3.0))), child: Column( children: [ Padding( - padding: const EdgeInsets.only(left: 5.0, right: 6.0, top: 3.5), - child: Text( - user.promo == '2024' ? 'SPE' : 'SUP', // TODO: Smart way, + padding: const EdgeInsets.only( + left: 5.0, + right: 6.0, + top: 3.5), + child: Text(promoName, style: TextStyle( height: 1, fontFamily: 'LatoE', fontSize: 17.0, - fontWeight: FontWeight.w600, - fontStyle: FontStyle.italic, - color: Colors.white - ) - ), + fontWeight: + FontWeight.w600, + fontStyle: + FontStyle.italic, + color: Colors.white)), ), ], ), @@ -259,8 +261,7 @@ class _MainPageState extends State fontSize: 18.0, fontFamily: 'Lato2', fontWeight: FontWeight.w600, - color: Colors.black - ), + color: Colors.black), ) ], ), @@ -268,7 +269,7 @@ class _MainPageState extends State ], ), Padding( - padding: const EdgeInsets.only(top: 12.5, left: 2.5), + padding: const EdgeInsets.only(top: 4), child: Text( 'Lyon - ${user.promo}', // Temporary, groups will be there then style: TextStyle( @@ -276,22 +277,18 @@ class _MainPageState extends State fontSize: 18, fontFamily: 'Lato', fontWeight: FontWeight.w700, - fontStyle: FontStyle.italic - ), + fontStyle: FontStyle.italic), ), ) ], ), - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - offset: Offset(1.0, 1.0), - blurRadius: 5.0, - color: Color.fromRGBO(28, 28, 28, 0.55), - ) - ] - ), + decoration: BoxDecoration(color: Colors.white, boxShadow: [ + BoxShadow( + offset: Offset(1.0, 1.0), + blurRadius: 5.0, + color: Color.fromRGBO(28, 28, 28, 0.55), + ) + ]), ), ), Container( @@ -299,63 +296,75 @@ class _MainPageState extends State padding: const EdgeInsets.only(left: 15.0, top: 20.0), child: Wrap( runSpacing: 10.0, - children: pages.where((page) => page.onlyIf == null || page.onlyIf()).map((page) { - bool selected = page == selectedPage; - BorderRadius borderRadius = BorderRadius.only( - topLeft: Radius.circular(5), - bottomLeft: Radius.circular(5) - ); + children: pages + .where((page) => page.onlyIf == null || page.onlyIf!()) + .map((page) { + bool selected = page == selectedPage; + BorderRadius borderRadius = BorderRadius.only( + topLeft: Radius.circular(5), + bottomLeft: Radius.circular(5)); - return Container( - decoration: BoxDecoration( - boxShadow: selected ? [ - BoxShadow( - offset: Offset(-1, 0), - blurRadius: 5.0, - color: Color.fromRGBO(62, 62, 62, 0.45) - ) - ] : [] - ), - child: Material( - color: selected ? Colors.white : null, - borderRadius: borderRadius, - child: InkWell( - borderRadius: borderRadius, - onTap: () { - if (page.action != null) { - if (page.action == 'logout') { - showLogoutDialog(); - } - } - else if (page.page != null || page.tabs.length > 0) { - setState(() { - selectedPage = page; - }); + return Container( + decoration: BoxDecoration( + boxShadow: selected + ? [ + BoxShadow( + offset: Offset(-1, 0), + blurRadius: 5.0, + color: Color.fromRGBO( + 62, 62, 62, 0.45)) + ] + : []), + child: Material( + color: selected ? Colors.white : null, + borderRadius: borderRadius, + child: InkWell( + borderRadius: borderRadius, + onTap: () { + if (page.action != null) { + if (page.action == 'logout') { + showLogoutDialog(); + } + } else if (page.page != null || + page.tabs.length > 0) { + setState(() { + selectedPage = page; + }); - Navigator.pop(context); - } - }, - child: Ink( - height: 55.0, - child: ListTile( - leading: SvgPicture.asset(page.icon, width: 24, color: selected ? primary : Colors.white), - title: Padding( - padding: const EdgeInsets.only(bottom: 1.0), - child: Text(page.title, style: TextStyle(color: selected ? primary : Colors.white)), - ), - trailing: SvgPicture.asset( - 'assets/icons/navigate_next.svg', - width: 30, - color: selected ? primary : Colors.white + Navigator.pop(context); + } + }, + child: Ink( + height: 55.0, + child: ListTile( + leading: SvgPicture.asset(page.icon, + width: 24, + color: + selected ? primary : Colors.white), + title: Padding( + padding: + const EdgeInsets.only(bottom: 1.0), + child: Text(page.title, + style: TextStyle( + color: selected + ? primary + : Colors.white)), + ), + trailing: SvgPicture.asset( + 'assets/icons/navigate_next.svg', + width: 30, + color: + selected ? primary : Colors.white), + contentPadding: EdgeInsets.only( + left: 20.0, right: 10.0), + ), ), - contentPadding: EdgeInsets.only(left: 20.0, right: 10.0), ), ), - ), - ), - ); - }).where((p) => p != null).toList() - ), + ); + }) + .where((p) => p != null) + .toList()), ), ) ], @@ -365,7 +374,6 @@ class _MainPageState extends State } } -void rebuildAll(BuildContext context) -{ - context.findAncestorStateOfType<_MainPageState>().rebuild(); +void rebuildAll(BuildContext context) { + context.findAncestorStateOfType<_MainPageState>()!.rebuild(); } diff --git a/lib/pages/manage/add_mimos_dialog.dart b/lib/pages/manage/add_mimos_dialog.dart index 35708e7..99a5161 100644 --- a/lib/pages/manage/add_mimos_dialog.dart +++ b/lib/pages/manage/add_mimos_dialog.dart @@ -22,18 +22,16 @@ import 'package:epilyon/widgets/button.dart'; import 'package:epilyon/widgets/dropdown.dart'; import 'package:epilyon/widgets/text_form_field.dart'; -class AddMimosDialog extends StatefulWidget -{ +class AddMimosDialog extends StatefulWidget { final void Function(Mimos) callback; - AddMimosDialog(this.callback, { Key key }) : super(key: key); + AddMimosDialog(this.callback, {Key? key}) : super(key: key); @override _AddMimosDialogState createState() => _AddMimosDialogState(); } -class _AddMimosDialogState extends State -{ +class _AddMimosDialogState extends State { final _formKey = GlobalKey(); var subject = 'Algo'; @@ -41,33 +39,23 @@ class _AddMimosDialogState extends State var titleController = TextEditingController(); var dateController = TextEditingController(); - DateTime date; + DateTime? date; - void submit() - { - if (_formKey.currentState.validate()) { + void submit() { + if (_formKey.currentState!.validate()) { Navigator.of(context).pop(); - widget.callback(Mimos( - subject, - int.parse(numberController.text), - titleController.text, - date - )); + widget.callback(Mimos(subject, int.parse(numberController.text), + titleController.text, date)); } } - void dateDialog() async - { + void dateDialog() async { var now = DateTime.now(); var last = new DateTime(now.year + (now.month > 8 ? 1 : 0), 7, 7); var date = await showDatePicker( - context: context, - firstDate: now, - initialDate: now, - lastDate: last - ); + context: context, firstDate: now, initialDate: now, lastDate: last); if (date == null) { return; @@ -80,12 +68,12 @@ class _AddMimosDialogState extends State } @override - Widget build(BuildContext context) - { + Widget build(BuildContext context) { return SimpleDialog( title: Text('Ajouter un MiMos'), titlePadding: EdgeInsets.only(top: 20.0, left: 20.0, bottom: 12.5), - contentPadding: EdgeInsets.only(bottom: 15.0, left: 15.0, right: 15.0, top: 7.5), + contentPadding: + EdgeInsets.only(bottom: 15.0, left: 15.0, right: 15.0, top: 7.5), children: [ Form( key: _formKey, @@ -94,15 +82,21 @@ class _AddMimosDialogState extends State children: [ Padding( padding: const EdgeInsets.only(bottom: 5.0), - child: Text('Matière', style: TextStyle(color: Color(0xFF555555)),), + child: Text( + 'Matière', + style: TextStyle(color: Color(0xFF555555)), + ), ), EpiDropdown( values: ['Algo', 'Maths', 'Physique', 'Élec'], - onChanged: (value) => subject = value, + onChanged: (value) => subject = value!, ), Padding( padding: const EdgeInsets.only(bottom: 5.0, top: 15.0), - child: Text('Numéro', style: TextStyle(color: Color(0xFF555555)),), + child: Text( + 'Numéro', + style: TextStyle(color: Color(0xFF555555)), + ), ), Padding( padding: const EdgeInsets.only(bottom: 10.0), @@ -114,7 +108,10 @@ class _AddMimosDialogState extends State ), Padding( padding: const EdgeInsets.only(bottom: 5.0, top: 5.0), - child: Text('Titre', style: TextStyle(color: Color(0xFF555555)),), + child: Text( + 'Titre', + style: TextStyle(color: Color(0xFF555555)), + ), ), Padding( padding: const EdgeInsets.only(bottom: 10.0), @@ -125,7 +122,10 @@ class _AddMimosDialogState extends State ), Padding( padding: const EdgeInsets.only(bottom: 5.0, top: 5.0), - child: Text('Pour le', style: TextStyle(color: Color(0xFF555555)),), + child: Text( + 'Pour le', + style: TextStyle(color: Color(0xFF555555)), + ), ), Padding( padding: const EdgeInsets.only(bottom: 22.5), @@ -135,14 +135,9 @@ class _AddMimosDialogState extends State onTap: dateDialog, ), ), - EpiButton( - text: 'Ajouter', - onPressed: submit - ) - ] - ) - ) + EpiButton(text: 'Ajouter', onPressed: submit) + ])) ], ); } -} \ No newline at end of file +} diff --git a/lib/pages/manage/manage.dart b/lib/pages/manage/manage.dart index 22388dc..3a927e1 100644 --- a/lib/pages/manage/manage.dart +++ b/lib/pages/manage/manage.dart @@ -25,78 +25,69 @@ import 'package:epilyon/widgets/button.dart'; import 'package:epilyon/widgets/card.dart'; import 'package:epilyon/widgets/dialogs.dart'; -class ManagePage extends StatefulWidget -{ - ManagePage({ Key key }) : super(key: key); +class ManagePage extends StatefulWidget { + ManagePage({Key? key}) : super(key: key); @override _ManagePageState createState() => _ManagePageState(); } -class _ManagePageState extends State -{ +class _ManagePageState extends State { var notificationController = TextEditingController(); - void addDelegateDialog() - { + void addDelegateDialog() { showInputDialog(context, - title: 'Ajouter un délégué', - content: 'E-Mail du délégué à ajouter :', - okText: 'Ajouter', - onConfirm: doAddDelegate, - email: true - ); + title: 'Ajouter un délégué', + content: 'E-Mail du délégué à ajouter :', + okText: 'Ajouter', + onConfirm: doAddDelegate, + email: true); } - void removeDelegateDialog(Delegate delegate) - { + void removeDelegateDialog(Delegate delegate) { showConfirmDialog(context, - title: 'Supprimer le délégué ?', - content: "Voulez-vous vraiment enlever '${delegate.name}' des délégués ?", - onConfirm: () => doRemoveDelegate(delegate), - okText: 'Supprimer' - ); + title: 'Supprimer le délégué ?', + content: + "Voulez-vous vraiment enlever '${delegate.name}' des délégués ?", + onConfirm: () => doRemoveDelegate(delegate), + okText: 'Supprimer'); } - void notifyAllDialog() - { + void notifyAllDialog() { showConfirmDialog(context, - title: 'Notifier tout le monde ?', - content: "Voulez vous envoyer à TOUTE LA PROMO une notification avec comme " - "contenu '${notificationController.text}' ?", - onConfirm: doNotifyAll, - okText: 'Envoyer' - ); + title: 'Notifier tout le monde ?', + content: + "Voulez vous envoyer à TOUTE LA PROMO une notification avec comme " + "contenu '${notificationController.text}' ?", + onConfirm: doNotifyAll, + okText: 'Envoyer'); } - void doAddDelegate(BuildContext context, String email) - { + void doAddDelegate(BuildContext context, String email) { addDelegate(email).then((name) { Navigator.of(context).pop(); - if (!delegates.any((del) => del.email == email)) { + if (!delegates!.any((del) => del.email == email)) { setState(() { - delegates.add(new Delegate(name, email)); + delegates!.add(new Delegate(name, email)); }); } }).catchError((err) { if (!(err is String)) { print('Error during delegate addition'); - print(err); + print(err); } showErrorDialog(this.context, title: 'Erreur', - content: "Impossible d'ajouter le délégué à l'email '$email'\n$err" - ); + content: "Impossible d'ajouter le délégué à l'email '$email'\n$err"); }); } - void doRemoveDelegate(Delegate delegate) - { + void doRemoveDelegate(Delegate delegate) { removeDelegate(delegate.email).then((_) { setState(() { - delegates.removeWhere((del) => del.email == delegate.email); + delegates!.removeWhere((del) => del.email == delegate.email); }); }).catchError((err) { if (!(err is String)) { @@ -106,13 +97,12 @@ class _ManagePageState extends State showErrorDialog(this.context, title: 'Erreur', - content: "Impossible de supprimer le délégué '${delegate.name}'\n$err" - ); + content: + "Impossible de supprimer le délégué '${delegate.name}'\n$err"); }); } - void doNotifyAll() - { + void doNotifyAll() { notifyAll(notificationController.text).then((_) { notificationController.text = ''; }).catchError((err) { @@ -121,110 +111,112 @@ class _ManagePageState extends State showErrorDialog(this.context, title: 'Erreur', - content: "Impossible d'envoyer la notification\n$err" - ); + content: "Impossible d'envoyer la notification\n$err"); }); } @override Widget build(BuildContext context) { - var user = getUser(); + var user = getUser()!; return Center( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(top: 35.0, bottom: 2.5), - child: Text('Vous êtes', style: TextStyle(fontSize: 30.0)), - ), - Text( - isUserAdmin() - ? 'Administrateur' - : (isUserDelegate() ? 'Délégué' : 'Rien du tout'), - style: TextStyle( - fontSize: 36.0, - fontWeight: FontWeight.bold, - fontStyle: FontStyle.italic - ), - ), - Padding( - padding: EdgeInsets.only(top: 2.5, bottom: !isUserAdmin() ? 10.0 : 35.0), - child: Text( - 'de la promo ' + user.promo, - style: TextStyle(fontSize: 24.0) - ), - ), - !isUserAdmin() ? Padding( - padding: const EdgeInsets.only(bottom: 30.0), - child: Text( - 'Administrateur : ' + data.admin.name, - style: TextStyle(fontSize: 17.0, fontStyle: FontStyle.italic) - ), - ) : Container(), - EpiCard( - title: 'Délégués', - bottomPadding: 10.0, - child: Column( - children: delegates.map((delegate) => Column( - children: [ - Divider( - height: 0 - ), - Padding( - padding: const EdgeInsets.symmetric(vertical: 9.5, horizontal: 12.5), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(top: 35.0, bottom: 2.5), + child: Text('Vous êtes', style: TextStyle(fontSize: 30.0)), + ), + Text( + isUserAdmin() + ? 'Administrateur' + : (isUserClassRep() ? 'Délégué' : 'Rien du tout'), + style: TextStyle( + fontSize: 36.0, + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic), + ), + Padding( + padding: + EdgeInsets.only(top: 2.5, bottom: !isUserAdmin() ? 10.0 : 35.0), + child: Text('de la promo ' + user.promo, + style: TextStyle(fontSize: 24.0)), + ), + !isUserAdmin() + ? Padding( + padding: const EdgeInsets.only(bottom: 30.0), + child: Text('Administrateur : ' + data.admin!.name!, + style: + TextStyle(fontSize: 17.0, fontStyle: FontStyle.italic)), + ) + : Container(), + EpiCard( + title: 'Délégués', + bottomPadding: 10.0, + child: Column( + children: delegates! + .map((delegate) => Column( children: [ - Text(delegate.name, style: TextStyle(fontSize: 16.0),), - isUserAdmin() ? InkWell( - child: SvgPicture.asset( - 'assets/icons/remove_circle.svg', - color: Color(0xFF9D0000), - height: 20 + Divider(height: 0), + Padding( + padding: const EdgeInsets.symmetric( + vertical: 9.5, horizontal: 12.5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + delegate.name!, + style: TextStyle(fontSize: 16.0), + ), + isUserAdmin() + ? InkWell( + child: SvgPicture.asset( + 'assets/icons/remove_circle.svg', + color: Color(0xFF9D0000), + height: 20), + onTap: () => + removeDelegateDialog(delegate), + ) + : Container() + ], ), - onTap: () => removeDelegateDialog(delegate), - ) : Container() + ) ], - ), - ) - ], - )).toList(), + )) + .toList(), + )), + isUserAdmin() + ? Padding( + padding: const EdgeInsets.only( + top: 30.0, left: 65.0, right: 65.0, bottom: 10.0), + child: EpiButton( + text: 'Ajouter un délégué', + onPressed: () => addDelegateDialog()), ) - ), - isUserAdmin() ? Padding( - padding: const EdgeInsets.only(top: 30.0, left: 65.0, right: 65.0, bottom: 10.0), - child: EpiButton( - text: 'Ajouter un délégué', - onPressed: () => addDelegateDialog() - ), - ) : Container(), - Padding( - padding: const EdgeInsets.only(top: 20.0, bottom: 15.0), - child: EpiCard( - title: 'Notifier toute la promo', - bottomPadding: 0, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0), - child: TextField( - maxLines: 5, - controller: notificationController, - ), + : Container(), + Padding( + padding: const EdgeInsets.only(top: 20.0, bottom: 15.0), + child: EpiCard( + title: 'Notifier toute la promo', + bottomPadding: 0, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0), + child: TextField( + maxLines: 5, + controller: notificationController, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 75.0, vertical: 15.0), - child: EpiButton( - text: 'Envoyer', - onPressed: notifyAllDialog - ), - ) - ], - ) - ), - ) - ], - ) - ); + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 75.0, vertical: 15.0), + child: + EpiButton(text: 'Envoyer', onPressed: notifyAllDialog), + ) + ], + )), + ) + ], + )); } -} \ No newline at end of file +} diff --git a/lib/pages/mcq/mcq_history.dart b/lib/pages/mcq/mcq_history.dart index 441b869..e01a98f 100644 --- a/lib/pages/mcq/mcq_history.dart +++ b/lib/pages/mcq/mcq_history.dart @@ -27,46 +27,41 @@ import 'package:epilyon/mcq.dart'; import 'package:epilyon/pages/base.dart'; import 'package:epilyon/pages/mcq/mcq_result.dart'; -class MCQHistoryPage extends StatefulWidget -{ - MCQHistoryPage({ Key key }) : super(key: key); +class MCQHistoryPage extends StatefulWidget { + MCQHistoryPage({Key? key}) : super(key: key); @override _MCQHistoryPageState createState() => _MCQHistoryPageState(); } -class _MCQHistoryPageState extends State -{ +class _MCQHistoryPageState extends State { @override - Widget build(BuildContext context) - { + Widget build(BuildContext context) { DateTime now = DateTime.now(); - DateTime firstSemester = DateTime(now.month < 8 ? now.year - 1 : now.year, 9, 1); - DateTime secondSemester = DateTime(now.month < 8 ? now.year : now.year + 1, 1, 1); + DateTime firstSemester = + DateTime(now.month < 8 ? now.year - 1 : now.year, 9, 1); + DateTime secondSemester = + DateTime(now.month < 8 ? now.year : now.year + 1, 1, 1); - // TODO: More dynamic way - var shift = getUser().promo == "2025" ? 0 : 2; + var semesterOffset = getYearAtEpita() * 2; return Center( child: Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), - child: Column( - children: [ - now.month >= 1 && now.month <= 6 - ? getSemester(2 + shift, secondSemester, now) - : Container(), - getSemester(1 + shift, firstSemester, secondSemester) - ] - ), + child: Column(children: [ + now.month >= 1 && now.month <= 6 + ? getSemester(2 + semesterOffset, secondSemester, now) + : Container(), + getSemester(1 + semesterOffset, firstSemester, secondSemester) + ]), ), ); } - Widget getSemester(int num, DateTime from, DateTime to) - { + Widget getSemester(int num, DateTime from, DateTime to) { DateFormat format = new DateFormat("dd MMMM", 'fr_FR'); - List mcqs = data.mcqHistory.where((mcq) { + List mcqs = data.mcqHistory!.where((mcq) { return mcq.date.compareTo(from) >= 0 && mcq.date.compareTo(to) < 0; }).toList(); @@ -76,64 +71,70 @@ class _MCQHistoryPageState extends State title: "Semestre n°$num", bottomPadding: 10.0, child: Column( - children: mcqs.map((mcq) => Column( - children: [ - Divider( - height: 0, - ), - buildEntry( - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (context) { - return BasePage( - title: 'QCM du ' + format.format(mcq.date), - child: MCQResultPage(mcq: mcq) - ); - })); - }, - isLast: mcq == mcqs[mcqs.length - 1], - child: Padding( - padding: EdgeInsets.only(bottom: mcq == mcqs[mcqs.length - 1] ? 1.5 : 0.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: mcqs + .map((mcq) => Column( children: [ - Padding( - padding: const EdgeInsets.only(left: 15.0), - child: Text(format.format(mcq.date), style: TextStyle(fontSize: 17.0)), + Divider( + height: 0, ), - Row( - children: [ - Text( - mcq.average.toStringAsFixed(1), - style: TextStyle(fontSize: 17.0, fontWeight: FontWeight.w500), - ), - Text('/20', style: TextStyle(fontSize: 17.0)), - Padding( - padding: const EdgeInsets.only(left: 20.0, right: 10.0), - child: SvgPicture.asset( - 'assets/icons/navigate_next.svg', - color: Colors.black, - width: 27.5, - ), + buildEntry( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) { + return BasePage( + title: 'QCM du ' + format.format(mcq.date), + child: MCQResultPage(mcq: mcq)); + })); + }, + isLast: mcq == mcqs[mcqs.length - 1], + child: Padding( + padding: EdgeInsets.only( + bottom: + mcq == mcqs[mcqs.length - 1] ? 1.5 : 0.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15.0), + child: Text(format.format(mcq.date), + style: TextStyle(fontSize: 17.0)), + ), + Row( + children: [ + Text( + mcq.average!.toStringAsFixed(1), + style: TextStyle( + fontSize: 17.0, + fontWeight: FontWeight.w500), + ), + Text('/20', + style: TextStyle(fontSize: 17.0)), + Padding( + padding: const EdgeInsets.only( + left: 20.0, right: 10.0), + child: SvgPicture.asset( + 'assets/icons/navigate_next.svg', + color: Colors.black, + width: 27.5, + ), + ), + ], + ) + ], ), - ], - ) + ), + ), ], - ), - ), - ), - ], - )).toList(), - ) - ), + )) + .toList(), + )), ); } - Widget buildEntry({ Widget child, Function() onTap, bool isLast }) - { + Widget buildEntry({Widget? child, Function()? onTap, required bool isLast}) { var borderRadius = BorderRadius.only( bottomLeft: Radius.circular(isLast ? 3.0 : 0.0), - bottomRight: Radius.circular(isLast ? 3.0 : 0.0) - ); + bottomRight: Radius.circular(isLast ? 3.0 : 0.0)); return Material( elevation: 0.0, @@ -149,4 +150,4 @@ class _MCQHistoryPageState extends State ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/mcq/mcq_result.dart b/lib/pages/mcq/mcq_result.dart index 6fe1099..3b0b084 100644 --- a/lib/pages/mcq/mcq_result.dart +++ b/lib/pages/mcq/mcq_result.dart @@ -22,25 +22,22 @@ import 'package:epilyon/widgets/card.dart'; import 'package:epilyon/data.dart'; import 'package:epilyon/mcq.dart'; -class MCQResultPage extends StatefulWidget -{ - final MCQ mcq; +class MCQResultPage extends StatefulWidget { + final MCQ? mcq; - MCQResultPage({ Key key, this.mcq }) : super(key: key); + MCQResultPage({Key? key, this.mcq}) : super(key: key); @override _MCQResultPageState createState() => _MCQResultPageState(); } -class _MCQResultPageState extends State -{ +class _MCQResultPageState extends State { Color greenGrade = Color(0xFF04C800); Color redGrade = Color(0xFFD90000); @override - Widget build(BuildContext context) - { - if (widget.mcq == null && data.mcqHistory.length == 0) { + Widget build(BuildContext context) { + if (widget.mcq == null && data.mcqHistory!.length == 0) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -49,18 +46,17 @@ class _MCQResultPageState extends State "Aucun résultat de QCM", style: TextStyle(fontSize: 18.0, fontStyle: FontStyle.italic), ), - ] - ), + ]), ); } - MCQ mcq = widget.mcq != null ? widget.mcq : data.mcqHistory[0]; - MCQ previous; + MCQ? mcq = widget.mcq != null ? widget.mcq : data.mcqHistory![0]; + MCQ? previous; - for (int i = 0; i < data.mcqHistory.length; i++) { - if (data.mcqHistory[i] == mcq) { - if (i + 1 < data.mcqHistory.length) { - previous = data.mcqHistory[i + 1]; + for (int i = 0; i < data.mcqHistory!.length; i++) { + if (data.mcqHistory![i] == mcq) { + if (i + 1 < data.mcqHistory!.length) { + previous = data.mcqHistory![i + 1]; } break; @@ -75,13 +71,13 @@ class _MCQResultPageState extends State child: Column( children: [ Text( - 'QCM du ' + format.format(mcq.date), + 'QCM du ' + format.format(mcq!.date), style: TextStyle(fontSize: 16), ), Padding( padding: const EdgeInsets.only(top: 20.0), child: Text( - mcq.average.toStringAsFixed(1) + '/20', + mcq.average!.toStringAsFixed(1) + '/20', style: TextStyle(fontSize: 52, fontWeight: FontWeight.bold), ), ), @@ -89,27 +85,33 @@ class _MCQResultPageState extends State 'Coefficienté', style: TextStyle(fontSize: 16, fontStyle: FontStyle.italic), ), - previous == null ? Container() : Padding( - padding: const EdgeInsets.only(top: 7.5, bottom: 7.5), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - compare(mcq.average, previous.average), - Text('par rapport au précédent', style: TextStyle(fontSize: 18.0)) - ], - ), - ), + previous == null + ? Container() + : Padding( + padding: const EdgeInsets.only(top: 7.5, bottom: 7.5), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + compare(mcq.average!, previous.average!), + Text('par rapport au précédent', + style: TextStyle(fontSize: 18.0)) + ], + ), + ), Padding( padding: const EdgeInsets.only(top: 32.5), child: EpiCard( title: 'Notes par matières', child: Padding( - padding: const EdgeInsets.only(left: 25.0, bottom: 10.0, right: 22.5), + padding: const EdgeInsets.only( + left: 25.0, bottom: 10.0, right: 22.5), child: Column( - children: mcq.grades.map((grade) { - MCQGrade last = previous == null + children: mcq.grades!.map((grade) { + MCQGrade? last = previous == null ? null - : previous.grades.firstWhere((g) => grade.subject == g.subject); + : previous.grades!.firstWhere( + (g) => grade.subject == g.subject, + orElse: () => grade); return Padding( padding: const EdgeInsets.only(bottom: 8), @@ -117,32 +119,39 @@ class _MCQResultPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - grade.subject, - style: TextStyle(fontSize: 17, fontWeight: FontWeight.w500), + grade.subject!, + style: TextStyle( + fontSize: 17, fontWeight: FontWeight.w500), ), Row( children: [ - previous == null ? Container() : Padding( - padding: EdgeInsets.only( - right: grade.grade == 10.0 - ? 4.0 - : (grade.grade < 0.0 ? 8.25 : 12.75) - ), - child: compare(grade.grade, last.grade), - ), + previous == null + ? Container() + : Padding( + padding: EdgeInsets.only( + right: grade.grade == 10.0 + ? 4.0 + : (grade.grade! < 0.0 + ? 8.25 + : 12.75)), + child: + compare(grade.grade!, last!.grade!), + ), Row( children: [ Text( - grade.grade.toStringAsFixed(1), + grade.grade!.toStringAsFixed(1), style: TextStyle( color: grade.grade == 10.0 ? greenGrade - : (grade.grade <= 0.0 ? redGrade : null), + : (grade.grade! <= 0.0 + ? redGrade + : null), fontSize: 17, - fontWeight: FontWeight.w500 - ), + fontWeight: FontWeight.w500), ), - Text('/10', style: TextStyle(fontSize: 17)) + Text('/10', + style: TextStyle(fontSize: 17)) ], ) ], @@ -152,8 +161,7 @@ class _MCQResultPageState extends State ); }).toList(), ), - ) - ), + )), ) ], ), @@ -161,15 +169,15 @@ class _MCQResultPageState extends State ); } - Widget compare(double a, double b) - { + Widget compare(double a, double b) { String sign = a < b ? '- ' : '+'; String grade = (a - b).abs().toStringAsFixed(1); Color color = a > b ? greenGrade : (a < b ? redGrade : Colors.black); return Padding( padding: const EdgeInsets.only(right: 4.0), - child: Text("($sign$grade)", style: TextStyle(fontSize: 18.0, color: color)), + child: + Text("($sign$grade)", style: TextStyle(fontSize: 18.0, color: color)), ); } -} \ No newline at end of file +} diff --git a/lib/pages/mimos.dart b/lib/pages/mimos.dart index 6ee0538..cef2220 100644 --- a/lib/pages/mimos.dart +++ b/lib/pages/mimos.dart @@ -30,7 +30,7 @@ class MimosPage extends StatefulWidget final bool canAdd; final bool canRemove; - MimosPage({ this.canAdd = false, this.canRemove = false, Key key }) : super(key: key); + MimosPage({ this.canAdd = false, this.canRemove = false, Key? key }) : super(key: key); @override _MimosPageState createState() => _MimosPageState(); @@ -59,7 +59,7 @@ class _MimosPageState extends State void doAddMimos(Mimos m) { addMimos(m).then((_) => setState(() { - mimos.add(m); + mimos!.add(m); })).catchError((err) { if (!(err is String)) { print('Error while adding mimos'); @@ -76,7 +76,7 @@ class _MimosPageState extends State void doRemoveMimos(Mimos m) { removeMimos(m.subject, m.number).then((_) => setState(() { - mimos.removeWhere((mm) => mm.number == m.number && mm.subject == m.subject); + mimos!.removeWhere((mm) => mm.number == m.number && mm.subject == m.subject); })).catchError((err) { if (!(err is String)) { print('Error while removing mimos'); @@ -93,11 +93,11 @@ class _MimosPageState extends State @override Widget build(BuildContext context) { - var weeks = Map>>(); + var weeks = Map>>(); - for (var m in mimos) { - var week = new DateTime(m.date.year, m.date.month, m.date.day); - week = week.subtract(new Duration(days: m.date.weekday - 1)); + for (var m in mimos!) { + var week = new DateTime(m.date!.year, m.date!.month, m.date!.day); + week = week.subtract(new Duration(days: m.date!.weekday - 1)); var weekStr = (week.day < 10 ? '0' : '') + week.day.toString() @@ -106,17 +106,17 @@ class _MimosPageState extends State + week.month.toString(); if (!weeks.containsKey(weekStr)) { - weeks[weekStr] = Map>(); + weeks[weekStr] = Map>(); for (var sub in ['Algo', 'Maths', 'Physique', 'Élec']) { - weeks[weekStr][sub] = []; + weeks[weekStr]![sub] = []; } } - if (!weeks[weekStr].containsKey(m.subject)) { - weeks[weekStr][m.subject] = []; + if (!weeks[weekStr]!.containsKey(m.subject)) { + weeks[weekStr]![m.subject] = []; } - weeks[weekStr][m.subject].add(m); + weeks[weekStr]![m.subject]!.add(m); } var cards = []; @@ -124,7 +124,7 @@ class _MimosPageState extends State var rows = []; subjects.forEach((subject, mimos) { - mimos.sort((a, b) => a.number.compareTo(b.number)); + mimos.sort((a, b) => a.number!.compareTo(b.number!)); for (int i = 0; i < mimos.length; i++) { rows.add(TableRow( @@ -132,7 +132,7 @@ class _MimosPageState extends State Padding( padding: const EdgeInsets.symmetric(vertical: 5.0), child: Text( - i == 0 ? subject : '', + i == 0 ? subject! : '', style: TextStyle( fontWeight: FontWeight.w500, fontSize: 19.0 @@ -154,7 +154,7 @@ class _MimosPageState extends State ), Flexible( child: TextOneLine( - mimos[i].title, + mimos[i].title!, overflow: TextOverflow.ellipsis, style: TextStyle( fontStyle: FontStyle.italic, diff --git a/lib/pages/ms_login.dart b/lib/pages/ms_login.dart index 3e2d0cc..a1a7968 100644 --- a/lib/pages/ms_login.dart +++ b/lib/pages/ms_login.dart @@ -25,47 +25,38 @@ import 'package:epilyon/data.dart'; import 'package:epilyon/auth.dart'; import 'package:epilyon/api_url.dart'; -class MSLoginPage extends StatefulWidget -{ - MSLoginPage({ Key key }) : super(key: key); +class MSLoginPage extends StatefulWidget { + MSLoginPage({Key? key}) : super(key: key); @override _MSLoginPageState createState() => _MSLoginPageState(); } -class _MSLoginPageState extends State -{ - BuildContext _dialogContext; +class _MSLoginPageState extends State { + BuildContext? _dialogContext; - Future _onWebViewCreated(WebViewController controller) async - { - controller.loadUrl(API_URL + "/auth/login", headers: { - "Token": getToken() - }); + Future _onWebViewCreated(WebViewController controller) async { + controller + .loadUrl(API_URL + "/auth/login", headers: {"Token": getToken()!}); } - void _onChannelMessage(BuildContext context, JavascriptMessage message) - { + void _onChannelMessage(BuildContext context, JavascriptMessage message) { if (message.message != 'Close') { return; } - showLoadingDialog( - context, + showLoadingDialog(context, title: 'Chargement', content: 'Lecture des données...', - onContextUpdate: (ctx) => _dialogContext = ctx - ); + onContextUpdate: (ctx) => _dialogContext = ctx); login().then((first) async { - if (first) { - Navigator.pop(_dialogContext); - showLoadingDialog( - context, + if (first!) { + Navigator.pop(_dialogContext!); + showLoadingDialog(context, title: 'Première connexion', content: 'Récupération des informations...', - onContextUpdate: (ctx) => _dialogContext = ctx - ); + onContextUpdate: (ctx) => _dialogContext = ctx); await forceRefresh(); } @@ -76,7 +67,7 @@ class _MSLoginPageState extends State return; } - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); pushMain(context); }).catchError((e, trace) async { if (_dialogContext == null) { @@ -85,34 +76,33 @@ class _MSLoginPageState extends State await cancelLogin(); - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); Navigator.pop(context); print('Error during login/data fetching : ' + e.toString()); print(trace); - showErrorDialog( - context, + showErrorDialog(context, title: 'Erreur', - content: 'Impossible de se connecter au serveur : ' + e.toString() - ); + content: 'Impossible de se connecter au serveur : ' + e.toString()); }); } @override - Widget build(BuildContext context) - { + Widget build(BuildContext context) { return BasePage( title: 'Connexion', fixed: true, child: WebView( javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: _onWebViewCreated, - javascriptChannels: Set.from([JavascriptChannel( - name: "Epilyon", - onMessageReceived: (message) => _onChannelMessage(context, message) - )]), + javascriptChannels: Set.from([ + JavascriptChannel( + name: "Epilyon", + onMessageReceived: (message) => + _onChannelMessage(context, message)) + ]), ), ); } -} \ No newline at end of file +} diff --git a/lib/pages/task/task_detail.dart b/lib/pages/task/task_detail.dart new file mode 100644 index 0000000..61fee07 --- /dev/null +++ b/lib/pages/task/task_detail.dart @@ -0,0 +1,66 @@ +/* + * Epilyon, keeping EPITA students organized + * Copyright (C) 2019-2020 Adrien 'Litarvan' Navratil + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import 'package:epilyon/task.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:intl/intl.dart'; + +class TaskDetailPage extends StatefulWidget { + final Task? task; + + TaskDetailPage({Key? key, this.task}) : super(key: key); + + @override + _TaskDetailPageState createState() => _TaskDetailPageState(); +} + +class _TaskDetailPageState extends State { + @override + Widget build(BuildContext context) { + if (widget.task == null) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Erreur 404", + style: TextStyle(fontSize: 18.0, fontStyle: FontStyle.italic), + ), + ]), + ); + } + + Task task = widget.task!; + + return Center( + child: Padding( + padding: const EdgeInsets.all(30.0), + child: Column( + children: [ + MarkdownBody(data: task.content!), + Padding( + padding: const EdgeInsets.only(top: 50.0, bottom: 7.5), + child: Text("Powered by Epitaf.fr", + style: TextStyle( + color: Color(0xFF888888), fontStyle: FontStyle.italic))) + ], + ), + ), + ); + } +} diff --git a/lib/pages/task/task_list.dart b/lib/pages/task/task_list.dart new file mode 100644 index 0000000..50f72e1 --- /dev/null +++ b/lib/pages/task/task_list.dart @@ -0,0 +1,145 @@ +/* + * Epilyon, keeping EPITA students organized + * Copyright (C) 2019-2020 Adrien 'Litarvan' Navratil + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import 'package:epilyon/pages/base.dart'; +import 'package:epilyon/pages/task/task_detail.dart'; +import 'package:flutter/material.dart'; +import 'package:assorted_layout_widgets/assorted_layout_widgets.dart'; + +import 'package:epilyon/task.dart'; +import 'package:epilyon/mimos.dart'; +import 'package:epilyon/widgets/card.dart'; +import 'package:epilyon/widgets/dialogs.dart'; +import 'package:epilyon/pages/manage/add_mimos_dialog.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:intl/intl.dart'; + +class TaskPage extends StatefulWidget { + final bool canAdd; + final bool canRemove; + + TaskPage({this.canAdd = false, this.canRemove = false, Key? key}) + : super(key: key); + + @override + _TaskPageState createState() => _TaskPageState(); +} + +class _TaskPageState extends State { + @override + Widget build(BuildContext context) { + final DateFormat dateFormatter = DateFormat('EEEE dd MMMM'); + + var days = Map>(); + + for (var t in tasks!) { + var dayStr = dateFormatter.format(t.dueDate!); + + if (!days.containsKey(dayStr)) { + days[dayStr] = []; + } + + days[dayStr]!.add(t); + } + + var sortedKeys = days.keys.toList(); + sortedKeys.sort( + (a, b) => dateFormatter.parse(a).compareTo(dateFormatter.parse(b))); + + var cards = []; + + cards.add(Padding( + padding: const EdgeInsets.only(top: 20.0, bottom: 7.5), + child: Text("Powered by Epitaf.fr", + style: TextStyle( + color: Color(0xFF888888), fontStyle: FontStyle.italic)))); + + sortedKeys.forEach((day) { + var tasks = days[day]!; + var rows = []; + + for (int i = 0; i < tasks.length; i++) { + rows.add(TableRow(children: [ + buildEntry( + onTap: () { + Navigator.push(context, MaterialPageRoute(builder: (context) { + return BasePage( + title: tasks[i].title, + child: TaskDetailPage(task: tasks[i])); + })); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container( + constraints: BoxConstraints(maxWidth: 200), + child: Padding( + padding: const EdgeInsets.only(left: 15.0), + child: Text(tasks[i].title!, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 17.0)), + )), + SvgPicture.asset('assets/icons/navigate_next.svg', + color: Colors.black, width: 27.5) + ], + )) + ])); + } + + cards.add(Padding( + padding: EdgeInsets.only( + top: 10.0, bottom: (day == sortedKeys.last) ? 30.0 : 7.5), + child: EpiCard( + title: day, + child: Padding( + padding: + const EdgeInsets.only(left: 22.5, right: 15.0, bottom: 15.0), + child: Table( + defaultVerticalAlignment: TableCellVerticalAlignment.middle, + columnWidths: {0: FractionColumnWidth(1)}, + children: rows, + ), + )), + )); + }); + + return Center( + child: Column( + children: cards, + ), + ); + } + + Widget buildEntry({Widget? child, Function()? onTap}) { + var borderRadius = BorderRadius.only( + bottomLeft: Radius.circular(0.0), bottomRight: Radius.circular(0.0)); + + return Material( + elevation: 0.0, + color: Colors.white, + borderRadius: borderRadius, + child: InkWell( + onTap: onTap, + borderRadius: borderRadius, + child: Ink( + height: 40.0, + child: child, + ), + ), + ); + } +} diff --git a/lib/task.dart b/lib/task.dart new file mode 100644 index 0000000..9e55696 --- /dev/null +++ b/lib/task.dart @@ -0,0 +1,38 @@ +import 'package:epilyon/data.dart'; + +List? get tasks => data.tasks; + +class Task { + DateTime? createdAt; + DateTime? updatedAt; + String? shortId; + String? visibility; + int? promotion; + String? semester; + String? region; + String? title; + String? subject; + String? content; + DateTime? dueDate; + String? createdByLogin; + String? createdBy; + String? updatedByLogin; + String? updatedBy; + + Task( + this.createdAt, + this.updatedAt, + this.shortId, + this.visibility, + this.promotion, + this.semester, + this.region, + this.title, + this.subject, + this.content, + this.dueDate, + this.createdByLogin, + this.createdBy, + this.updatedByLogin, + this.updatedBy); +} diff --git a/lib/widgets/button.dart b/lib/widgets/button.dart index 5f86fc1..4bd7e79 100644 --- a/lib/widgets/button.dart +++ b/lib/widgets/button.dart @@ -22,7 +22,7 @@ class EpiButton extends StatelessWidget final GestureTapCallback onPressed; final String text; - EpiButton({ @required this.text, @required this.onPressed }); + EpiButton({ required this.text, required this.onPressed }); @override Widget build(BuildContext context) diff --git a/lib/widgets/card.dart b/lib/widgets/card.dart index 3cfdef7..2108565 100644 --- a/lib/widgets/card.dart +++ b/lib/widgets/card.dart @@ -26,8 +26,8 @@ class EpiCard extends StatelessWidget final double bottomPadding; EpiCard({ - @required this.title, - @required this.child, + required this.title, + required this.child, this.fullSize = true, this.bottomPadding = 12.5 diff --git a/lib/widgets/content.dart b/lib/widgets/content.dart index b26912a..163966a 100644 --- a/lib/widgets/content.dart +++ b/lib/widgets/content.dart @@ -26,8 +26,8 @@ import 'package:epilyon/widgets/dialogs.dart'; class EpiContent extends StatefulWidget { - final Widget child; - final bool fixed; + final Widget? child; + final bool? fixed; final bool doRefresh; EpiContent({ this.child, this.fixed, this.doRefresh = false }); @@ -38,7 +38,7 @@ class EpiContent extends StatefulWidget class EpiContentState extends State { - BuildContext _dialogContext; + BuildContext? _dialogContext; @override void initState() @@ -47,7 +47,7 @@ class EpiContentState extends State canRefresh().then((canRefresh) { if (widget.doRefresh && canRefresh) { - SchedulerBinding.instance.addPostFrameCallback((_) => doRefresh()); + SchedulerBinding.instance!.addPostFrameCallback((_) => doRefresh()); } }); } @@ -129,7 +129,7 @@ class EpiContentState extends State return; } - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); Navigator.push( context, MaterialPageRoute(builder: (context) => MSLoginPage()) @@ -142,7 +142,7 @@ class EpiContentState extends State print('Error during session creation : ' + e.toString()); print(trace); - Navigator.pop(_dialogContext); + Navigator.pop(_dialogContext!); showErrorDialog( context, title: 'Erreur', @@ -154,7 +154,7 @@ class EpiContentState extends State @override Widget build(BuildContext context) { - return widget.fixed ? widget.child : SingleChildScrollView( + return widget.fixed! ? widget.child! : SingleChildScrollView( child: widget.child, ); } diff --git a/lib/widgets/dialogs.dart b/lib/widgets/dialogs.dart index 68733ae..ac44be9 100644 --- a/lib/widgets/dialogs.dart +++ b/lib/widgets/dialogs.dart @@ -19,34 +19,34 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void showLoadingDialog(BuildContext context, { - String title, - String content, - Function(BuildContext context) onContextUpdate + String? title, + String? content, + Function(BuildContext? context)? onContextUpdate }) { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { - onContextUpdate(context); + onContextUpdate!(context); return LoadingDialog( - title: Text(title), - content: Text(content), + title: Text(title!), + content: Text(content!), ); } ).whenComplete(() { - onContextUpdate(null); + onContextUpdate!(null); }); } -void showErrorDialog(BuildContext context, { String title, String content }) +void showErrorDialog(BuildContext context, { String? title, String? content }) { showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(title), - content: Text(content), + title: Text(title!), + content: Text(content!), actions: [ FlatButton( child: Text("OK :("), @@ -60,17 +60,17 @@ void showErrorDialog(BuildContext context, { String title, String content }) } void showConfirmDialog(BuildContext context, { - String title, - String content, - void Function() onConfirm, + String? title, + String? content, + void Function()? onConfirm, String okText = 'Oui', String cancelText = 'Annuler' }) { showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(title), - content: Text(content), + title: Text(title!), + content: Text(content!), actions: [ FlatButton( child: Text(cancelText), @@ -82,7 +82,7 @@ void showConfirmDialog(BuildContext context, { child: Text(okText), onPressed: () { Navigator.of(context).pop(); - onConfirm(); + onConfirm!(); }, ) ], @@ -91,10 +91,10 @@ void showConfirmDialog(BuildContext context, { } void showInputDialog(BuildContext context, { - String title, - String content, - void Function(BuildContext, String) onConfirm, - String okText, + String? title, + String? content, + void Function(BuildContext, String)? onConfirm, + String? okText, String cancelText = 'Annuler', bool email = false }) { @@ -104,12 +104,12 @@ void showInputDialog(BuildContext context, { showDialog( context: context, builder: (BuildContext context) => AlertDialog( - title: Text(title), + title: Text(title!), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text(content), + Text(content!), TextField( keyboardType: email ? TextInputType.emailAddress : TextInputType.text, autofocus: true, @@ -130,9 +130,9 @@ void showInputDialog(BuildContext context, { }, ), FlatButton( - child: Text(okText), + child: Text(okText!), onPressed: () { - onConfirm(context, controller.text); + onConfirm!(context, controller.text); }, ) ], @@ -143,8 +143,8 @@ void showInputDialog(BuildContext context, { class LoadingDialog extends SimpleDialog { LoadingDialog({ - Widget title, - Widget content + Widget? title, + Widget? content }) : super( title: title, children: [ diff --git a/lib/widgets/dropdown.dart b/lib/widgets/dropdown.dart index dae684e..c4e0fee 100644 --- a/lib/widgets/dropdown.dart +++ b/lib/widgets/dropdown.dart @@ -21,16 +21,16 @@ import 'package:flutter_svg/svg.dart'; class EpiDropdown extends StatefulWidget { final List values; - final void Function(String) onChanged; + final void Function(String?) onChanged; - EpiDropdown({ @required this.values, @required this.onChanged }); + EpiDropdown({ required this.values, required this.onChanged }); _EpiDropdownState createState() => _EpiDropdownState(); } class _EpiDropdownState extends State { - String value; + String? value; @override Widget build(BuildContext context) @@ -64,7 +64,7 @@ class _EpiDropdownState extends State child: Text(value), ); }).toList(), - onChanged: (value) { + onChanged: (dynamic value) { setState(() => this.value = value); widget.onChanged(value); }, diff --git a/lib/widgets/refresh_button.dart b/lib/widgets/refresh_button.dart index 0b09e38..f073ff7 100644 --- a/lib/widgets/refresh_button.dart +++ b/lib/widgets/refresh_button.dart @@ -36,8 +36,8 @@ class RefreshButton extends StatefulWidget class _RefreshButtonState extends State with SingleTickerProviderStateMixin { - AnimationController _animationController; - Animation _animation; + late AnimationController _animationController; + late Animation _animation; var _refreshing = false; diff --git a/lib/widgets/text_form_field.dart b/lib/widgets/text_form_field.dart index 02f45cd..56b10cc 100644 --- a/lib/widgets/text_form_field.dart +++ b/lib/widgets/text_form_field.dart @@ -3,11 +3,11 @@ import 'package:flutter/services.dart'; class EpiTextFormField extends StatelessWidget { - final TextEditingController controller; + final TextEditingController? controller; final bool number; final bool readonly; - final void Function() callback; - final void Function() onTap; + final void Function()? callback; + final void Function()? onTap; EpiTextFormField({ this.controller, @@ -31,7 +31,7 @@ class EpiTextFormField extends StatelessWidget })] : [], onFieldSubmitted: (_) { if (callback != null){ - callback(); + callback!(); } }, onTap: onTap, @@ -59,9 +59,9 @@ class EpiTextFormField extends StatelessWidget ); } - String emptyValidator(String value) + String? emptyValidator(String? value) { - if (value.isEmpty) { + if (value!.isEmpty) { return 'Ce champ ne peut pas être vide'; } diff --git a/pubspec.lock b/pubspec.lock index 60f510c..fa4a117 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,132 +1,160 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" assorted_layout_widgets: dependency: "direct main" description: name: assorted_layout_widgets url: "https://pub.dartlang.org" source: hosted - version: "1.3.3" + version: "5.2.1" async: dependency: transitive description: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0-nullsafety" + version: "2.8.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety" + version: "2.1.0" cached_network_image: dependency: "direct main" description: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "2.3.1" + version: "3.1.0+1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety.2" + version: "1.1.0" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety" + version: "1.3.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" + version: "1.1.0" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.15.0-nullsafety.2" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" + version: "1.15.0" crypto: dependency: transitive description: name: crypto url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "3.0.1" cupertino_icons: dependency: "direct main" description: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "1.0.4" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" - file: + version: "1.2.0" + ffi: dependency: transitive description: - name: file + name: ffi url: "https://pub.dartlang.org" source: hosted - version: "5.2.1" - firebase: + version: "1.1.2" + file: dependency: transitive description: - name: firebase + name: file url: "https://pub.dartlang.org" source: hosted - version: "7.3.0" + version: "6.1.2" firebase_core: - dependency: transitive + dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "0.5.0" + version: "1.10.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "4.1.0" firebase_core_web: dependency: transitive description: name: firebase_core_web url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "1.2.0" firebase_messaging: dependency: "direct main" description: name: firebase_messaging url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "11.1.0" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.9" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" flutter: dependency: "direct main" description: flutter @@ -138,21 +166,28 @@ packages: name: flutter_blurhash url: "https://pub.dartlang.org" source: hosted - version: "0.5.0" + version: "0.6.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager url: "https://pub.dartlang.org" source: hosted - version: "1.4.1" + version: "3.1.3" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.9" flutter_svg: dependency: "direct main" description: name: flutter_svg url: "https://pub.dartlang.org" source: hosted - version: "0.18.1" + version: "0.23.0+1" flutter_test: dependency: "direct dev" description: flutter @@ -169,203 +204,203 @@ packages: name: http url: "https://pub.dartlang.org" source: hosted - version: "0.12.2" + version: "0.13.4" http_parser: dependency: transitive description: name: http_parser url: "https://pub.dartlang.org" source: hosted - version: "3.1.4" + version: "4.0.0" intl: dependency: "direct main" description: name: intl url: "https://pub.dartlang.org" source: hosted - version: "0.16.1" + version: "0.17.0" js: dependency: transitive description: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.2" + version: "0.6.3" + markdown: + dependency: transitive + description: + name: markdown + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.1" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10-nullsafety" + version: "0.12.10" matrix4_transform: dependency: transitive description: name: matrix4_transform url: "https://pub.dartlang.org" source: hosted - version: "1.1.4" + version: "2.0.1" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.2" + version: "1.7.0" octo_image: dependency: transitive description: name: octo_image url: "https://pub.dartlang.org" source: hosted - version: "0.2.1" + version: "1.0.0+1" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety" + version: "1.8.0" path_drawing: dependency: transitive description: name: path_drawing url: "https://pub.dartlang.org" source: hosted - version: "0.4.1+1" + version: "0.5.1+1" path_parsing: dependency: transitive description: name: path_parsing url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.2.1" path_provider: dependency: transitive description: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "1.6.14" + version: "2.0.6" path_provider_linux: dependency: transitive description: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+2" + version: "2.1.0" path_provider_macos: dependency: transitive description: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+3" + version: "2.0.2" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "2.0.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" pedantic: dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.9.2" + version: "1.11.1" petitparser: dependency: transitive description: name: petitparser url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "4.4.0" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" - platform_detect: - dependency: transitive - description: - name: platform_detect - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.0" + version: "3.0.2" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.2" + version: "2.0.2" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.13" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "1.4.4" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" + version: "4.2.4" rxdart: dependency: transitive description: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.24.1" + version: "0.27.2" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.10" + version: "2.0.8" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.2+2" + version: "2.0.2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+10" + version: "2.0.2" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.4" + version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.2+7" + version: "2.0.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" sky_engine: dependency: transitive description: flutter @@ -377,140 +412,175 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0-nullsafety" + version: "1.8.1" sqflite: dependency: transitive description: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "1.3.1+1" + version: "2.0.0+4" sqflite_common: dependency: transitive description: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "1.0.2+1" + version: "2.0.1+1" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.10.0-nullsafety" + version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0-nullsafety" + version: "1.1.0" synchronized: dependency: transitive description: name: synchronized url: "https://pub.dartlang.org" source: hosted - version: "2.2.0+2" + version: "3.0.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0-nullsafety" + version: "1.2.0" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19-nullsafety" + version: "0.4.2" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.0-nullsafety.2" + version: "1.3.0" url_launcher: dependency: "direct main" description: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "5.5.2" + version: "6.0.12" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+1" + version: "2.0.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+7" + version: "2.0.2" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.8" + version: "2.0.4" url_launcher_web: dependency: transitive description: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.3+1" + version: "2.0.4" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" uuid: dependency: transitive description: name: uuid url: "https://pub.dartlang.org" source: hosted - version: "2.2.2" + version: "3.0.5" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0-nullsafety.2" + version: "2.1.0" webview_flutter: dependency: "direct main" description: name: webview_flutter url: "https://pub.dartlang.org" source: hosted - version: "0.3.22+1" + version: "2.3.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.4.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.10" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.1.2" + version: "0.2.0" xml: dependency: transitive description: name: xml url: "https://pub.dartlang.org" source: hosted - version: "4.4.1" + version: "5.3.1" sdks: - dart: ">=2.10.0-0.0.dev <2.10.0" - flutter: ">=1.20.0 <2.0.0" + dart: ">=2.14.0 <3.0.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 201f752..ef021b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,21 +3,23 @@ description: Keeping EPITA students organized version: 0.1.0+1 environment: - sdk: ">=2.1.0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: flutter: sdk: flutter - cupertino_icons: ^0.1.3 - flutter_svg: ^0.18.1 - url_launcher: ^5.5.2 - http: ^0.12.2 - shared_preferences: ^0.5.10 - webview_flutter: ^0.3.22+1 - intl: ^0.16.1 - firebase_messaging: ^7.0.0 - cached_network_image: ^2.3.1 - assorted_layout_widgets: ^1.3.3 + cupertino_icons: ^1.0.4 + flutter_svg: ^0.23.0 + url_launcher: ^6.0.12 + http: ^0.13.4 + shared_preferences: ^2.0.8 + webview_flutter: ^2.3.0 + intl: ^0.17.0 + firebase_core: ^1.10.0 + firebase_messaging: ^11.1.0 + cached_network_image: ^3.1.0 + assorted_layout_widgets: ^5.2.1 + flutter_markdown: ^0.6.9 dev_dependencies: flutter_test: @@ -53,6 +55,7 @@ flutter: - assets/icons/wb_sunny.svg - assets/icons/work.svg - assets/images/login_background.jpg + - assets/images/default_thumb.jpg fonts: - family: LatoE fonts: