WT1.1.11 Null-Safe migration
This commit is contained in:
parent
a656562c49
commit
01148c6e39
@ -50,6 +50,10 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="flutterEmbedding"
|
android:name="flutterEmbedding"
|
||||||
android:value="2" />
|
android:value="2" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.firebase.messaging.default_notification_channel_id"
|
||||||
|
android:value="high_importance_channel" />
|
||||||
|
|
||||||
<meta-data android:name="com.facebook.sdk.ApplicationId"
|
<meta-data android:name="com.facebook.sdk.ApplicationId"
|
||||||
android:value="@string/facebook_app_id"/>
|
android:value="@string/facebook_app_id"/>
|
||||||
|
@ -408,6 +408,7 @@
|
|||||||
"Start":"Start",
|
"Start":"Start",
|
||||||
"Compact Test":"Compact Test",
|
"Compact Test":"Compact Test",
|
||||||
"Custom Test":"Custom Test",
|
"Custom Test":"Custom Test",
|
||||||
"Set": "Set"
|
"Set": "Set",
|
||||||
|
"Add this exercise to execute it paralell":"Add this exercise to execute it paralell"
|
||||||
|
|
||||||
}
|
}
|
@ -404,7 +404,8 @@
|
|||||||
"Start":"Kezdd el",
|
"Start":"Kezdd el",
|
||||||
"Compact Test":"Kompakt teszt",
|
"Compact Test":"Kompakt teszt",
|
||||||
"Custom Test":"Egyedi teszt",
|
"Custom Test":"Egyedi teszt",
|
||||||
"Set": "Széria"
|
"Set": "Széria",
|
||||||
|
"Add this exercise to execute it paralell":"Adj hozzá egy gyakorlatot a párhuzamos végrehajtáshoz"
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '10.0'
|
platform :ios, '12.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
289
ios/Podfile.lock
289
ios/Podfile.lock
@ -6,102 +6,92 @@ PODS:
|
|||||||
- AppAuth/ExternalUserAgent (1.4.0)
|
- AppAuth/ExternalUserAgent (1.4.0)
|
||||||
- apple_sign_in (0.0.1):
|
- apple_sign_in (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- audioplayer (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- devicelocale (0.0.1):
|
- devicelocale (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FBSDKCoreKit (9.0.0):
|
- FBSDKCoreKit (9.1.0):
|
||||||
- FBSDKCoreKit/Basics (= 9.0.0)
|
- FBSDKCoreKit/Basics (= 9.1.0)
|
||||||
- FBSDKCoreKit/Core (= 9.0.0)
|
- FBSDKCoreKit/Core (= 9.1.0)
|
||||||
- FBSDKCoreKit/Basics (9.0.0)
|
- FBSDKCoreKit/Basics (9.1.0)
|
||||||
- FBSDKCoreKit/Core (9.0.0):
|
- FBSDKCoreKit/Core (9.1.0):
|
||||||
- FBSDKCoreKit/Basics
|
- FBSDKCoreKit/Basics
|
||||||
- FBSDKLoginKit (9.0.0):
|
- FBSDKLoginKit (9.1.0):
|
||||||
- FBSDKLoginKit/Login (= 9.0.0)
|
- FBSDKLoginKit/Login (= 9.1.0)
|
||||||
- FBSDKLoginKit/Login (9.0.0):
|
- FBSDKLoginKit/Login (9.1.0):
|
||||||
- FBSDKCoreKit (~> 9.0.0)
|
- FBSDKCoreKit (~> 9.1.0)
|
||||||
- Firebase/Analytics (6.33.0):
|
- Firebase/Analytics (7.3.0):
|
||||||
- Firebase/Core
|
- Firebase/Core
|
||||||
- Firebase/Auth (6.33.0):
|
- Firebase/Auth (7.3.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseAuth (~> 6.9.2)
|
- FirebaseAuth (~> 7.3.0)
|
||||||
- Firebase/Core (6.33.0):
|
- Firebase/Core (7.3.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseAnalytics (= 6.8.3)
|
- FirebaseAnalytics (= 7.3.0)
|
||||||
- Firebase/CoreOnly (6.33.0):
|
- Firebase/CoreOnly (7.3.0):
|
||||||
- FirebaseCore (= 6.10.3)
|
- FirebaseCore (= 7.3.0)
|
||||||
- Firebase/Messaging (6.33.0):
|
- Firebase/Messaging (7.3.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 4.7.0)
|
- FirebaseMessaging (~> 7.3.0)
|
||||||
- firebase_analytics (6.3.0):
|
- firebase_analytics (8.0.0-dev.0):
|
||||||
- Firebase/Analytics (~> 6.33.0)
|
- Firebase/Analytics (= 7.3.0)
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_auth (0.18.4-1):
|
- firebase_auth (1.0.1):
|
||||||
- Firebase/Auth (~> 6.33.0)
|
- Firebase/Auth (= 7.3.0)
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (0.5.3):
|
- firebase_core (1.0.2):
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
- Firebase/CoreOnly (= 7.3.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (7.0.3):
|
- firebase_messaging (9.1.0):
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
- Firebase/Messaging (= 7.3.0)
|
||||||
- Firebase/Messaging (~> 6.33.0)
|
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseAnalytics (6.8.3):
|
- FirebaseAnalytics (7.3.0):
|
||||||
- FirebaseCore (~> 6.10)
|
- FirebaseCore (~> 7.0)
|
||||||
- FirebaseInstallations (~> 1.6)
|
- FirebaseInstallations (~> 7.0)
|
||||||
- GoogleAppMeasurement (= 6.8.3)
|
- GoogleAppMeasurement (= 7.3.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 6.7)
|
- GoogleUtilities/MethodSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/Network (~> 6.7)
|
- GoogleUtilities/Network (~> 7.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 6.7)"
|
- "GoogleUtilities/NSData+zlib (~> 7.0)"
|
||||||
- nanopb (~> 1.30906.0)
|
- nanopb (~> 2.30906.0)
|
||||||
- FirebaseAuth (6.9.2):
|
- FirebaseAuth (7.3.0):
|
||||||
- FirebaseCore (~> 6.10)
|
- FirebaseCore (~> 7.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GTMSessionFetcher/Core (~> 1.1)
|
- GTMSessionFetcher/Core (~> 1.4)
|
||||||
- FirebaseCore (6.10.3):
|
- FirebaseCore (7.3.0):
|
||||||
- FirebaseCoreDiagnostics (~> 1.6)
|
- FirebaseCoreDiagnostics (~> 7.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GoogleUtilities/Logger (~> 6.7)
|
- GoogleUtilities/Logger (~> 7.0)
|
||||||
- FirebaseCoreDiagnostics (1.7.0):
|
- FirebaseCoreDiagnostics (7.3.0):
|
||||||
- GoogleDataTransport (~> 7.4)
|
- GoogleDataTransport (~> 8.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GoogleUtilities/Logger (~> 6.7)
|
- GoogleUtilities/Logger (~> 7.0)
|
||||||
- nanopb (~> 1.30906.0)
|
- nanopb (~> 2.30906.0)
|
||||||
- FirebaseInstallations (1.7.0):
|
- FirebaseInstallations (7.9.0):
|
||||||
- FirebaseCore (~> 6.10)
|
- FirebaseCore (~> 7.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||||
- PromisesObjC (~> 1.2)
|
- PromisesObjC (~> 1.2)
|
||||||
- FirebaseInstanceID (4.8.0):
|
- FirebaseInstanceID (7.9.0):
|
||||||
- FirebaseCore (~> 6.10)
|
- FirebaseCore (~> 7.0)
|
||||||
- FirebaseInstallations (~> 1.6)
|
- FirebaseInstallations (~> 7.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||||
- FirebaseMessaging (4.7.1):
|
- FirebaseMessaging (7.3.0):
|
||||||
- FirebaseCore (~> 6.10)
|
- FirebaseCore (~> 7.0)
|
||||||
- FirebaseInstanceID (~> 4.7)
|
- FirebaseInstanceID (~> 7.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
- GoogleUtilities/Environment (~> 7.0)
|
||||||
- GoogleUtilities/Reachability (~> 6.7)
|
- GoogleUtilities/Reachability (~> 7.0)
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
- GoogleUtilities/UserDefaults (~> 7.0)
|
||||||
- Protobuf (>= 3.9.2, ~> 3.9)
|
|
||||||
- flurry (0.0.4):
|
|
||||||
- Flurry-iOS-SDK/FlurrySDK
|
|
||||||
- Flutter
|
|
||||||
- Flurry-iOS-SDK/FlurrySDK (11.2.0)
|
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_facebook_auth (1.0.0):
|
- flutter_facebook_auth (2.0.0):
|
||||||
- FBSDKCoreKit (~> 9.0.0)
|
- FBSDKCoreKit (~> 9.1.0)
|
||||||
- FBSDKLoginKit (~> 9.0.0)
|
- FBSDKLoginKit (~> 9.1.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_keyboard_visibility (0.0.1):
|
- flutter_local_notifications (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_secure_storage (3.3.1):
|
- flutter_secure_storage (3.3.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -111,36 +101,36 @@ PODS:
|
|||||||
- google_sign_in (0.0.1):
|
- google_sign_in (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- GoogleSignIn (~> 5.0)
|
- GoogleSignIn (~> 5.0)
|
||||||
- GoogleAppMeasurement (6.8.3):
|
- GoogleAppMeasurement (7.3.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
- GoogleUtilities/AppDelegateSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 6.7)
|
- GoogleUtilities/MethodSwizzler (~> 7.0)
|
||||||
- GoogleUtilities/Network (~> 6.7)
|
- GoogleUtilities/Network (~> 7.0)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 6.7)"
|
- "GoogleUtilities/NSData+zlib (~> 7.0)"
|
||||||
- nanopb (~> 1.30906.0)
|
- nanopb (~> 2.30906.0)
|
||||||
- GoogleDataTransport (7.5.1):
|
- GoogleDataTransport (8.1.0):
|
||||||
- nanopb (~> 1.30906.0)
|
- nanopb (~> 2.30906.0)
|
||||||
- GoogleSignIn (5.0.2):
|
- GoogleSignIn (5.0.2):
|
||||||
- AppAuth (~> 1.2)
|
- AppAuth (~> 1.2)
|
||||||
- GTMAppAuth (~> 1.0)
|
- GTMAppAuth (~> 1.0)
|
||||||
- GTMSessionFetcher/Core (~> 1.1)
|
- GTMSessionFetcher/Core (~> 1.1)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (6.7.2):
|
- GoogleUtilities/AppDelegateSwizzler (7.3.1):
|
||||||
- GoogleUtilities/Environment
|
- GoogleUtilities/Environment
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GoogleUtilities/Network
|
- GoogleUtilities/Network
|
||||||
- GoogleUtilities/Environment (6.7.2):
|
- GoogleUtilities/Environment (7.3.1):
|
||||||
- PromisesObjC (~> 1.2)
|
- PromisesObjC (~> 1.2)
|
||||||
- GoogleUtilities/Logger (6.7.2):
|
- GoogleUtilities/Logger (7.3.1):
|
||||||
- GoogleUtilities/Environment
|
- GoogleUtilities/Environment
|
||||||
- GoogleUtilities/MethodSwizzler (6.7.2):
|
- GoogleUtilities/MethodSwizzler (7.3.1):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GoogleUtilities/Network (6.7.2):
|
- GoogleUtilities/Network (7.3.1):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- "GoogleUtilities/NSData+zlib"
|
- "GoogleUtilities/NSData+zlib"
|
||||||
- GoogleUtilities/Reachability
|
- GoogleUtilities/Reachability
|
||||||
- "GoogleUtilities/NSData+zlib (6.7.2)"
|
- "GoogleUtilities/NSData+zlib (7.3.1)"
|
||||||
- GoogleUtilities/Reachability (6.7.2):
|
- GoogleUtilities/Reachability (7.3.1):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GoogleUtilities/UserDefaults (6.7.2):
|
- GoogleUtilities/UserDefaults (7.3.1):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- GTMAppAuth (1.1.0):
|
- GTMAppAuth (1.1.0):
|
||||||
- AppAuth/Core (~> 1.4)
|
- AppAuth/Core (~> 1.4)
|
||||||
@ -150,25 +140,26 @@ PODS:
|
|||||||
- GTMSessionFetcher/Core (1.5.0)
|
- GTMSessionFetcher/Core (1.5.0)
|
||||||
- GTMSessionFetcher/Full (1.5.0):
|
- GTMSessionFetcher/Full (1.5.0):
|
||||||
- GTMSessionFetcher/Core (= 1.5.0)
|
- GTMSessionFetcher/Core (= 1.5.0)
|
||||||
- nanopb (1.30906.0):
|
- modal_progress_hud_nsn (0.0.1):
|
||||||
- nanopb/decode (= 1.30906.0)
|
- Flutter
|
||||||
- nanopb/encode (= 1.30906.0)
|
- nanopb (2.30906.0):
|
||||||
- nanopb/decode (1.30906.0)
|
- nanopb/decode (= 2.30906.0)
|
||||||
- nanopb/encode (1.30906.0)
|
- nanopb/encode (= 2.30906.0)
|
||||||
|
- nanopb/decode (2.30906.0)
|
||||||
|
- nanopb/encode (2.30906.0)
|
||||||
- package_info (0.0.1):
|
- package_info (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- path_provider (0.0.1):
|
- path_provider (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- PromisesObjC (1.2.12)
|
- PromisesObjC (1.2.12)
|
||||||
- Protobuf (3.14.0)
|
- Purchases (3.10.6):
|
||||||
- Purchases (3.9.2):
|
- PurchasesCoreSwift (= 3.10.6)
|
||||||
- PurchasesCoreSwift (= 3.9.2)
|
- purchases_flutter (3.1.0):
|
||||||
- purchases_flutter (2.0.3):
|
|
||||||
- Flutter
|
- Flutter
|
||||||
- PurchasesHybridCommon (= 1.5.0)
|
- PurchasesHybridCommon (= 1.6.1)
|
||||||
- PurchasesCoreSwift (3.9.2)
|
- PurchasesCoreSwift (3.10.6)
|
||||||
- PurchasesHybridCommon (1.5.0):
|
- PurchasesHybridCommon (1.6.1):
|
||||||
- Purchases (= 3.9.2)
|
- Purchases (= 3.10.6)
|
||||||
- shared_preferences (0.0.1):
|
- shared_preferences (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- smartlook (0.0.5):
|
- smartlook (0.0.5):
|
||||||
@ -185,18 +176,17 @@ PODS:
|
|||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`)
|
- apple_sign_in (from `.symlinks/plugins/apple_sign_in/ios`)
|
||||||
- audioplayer (from `.symlinks/plugins/audioplayer/ios`)
|
|
||||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||||
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- flurry (from `.symlinks/plugins/flurry/ios`)
|
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
|
- google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
|
||||||
|
- modal_progress_hud_nsn (from `.symlinks/plugins/modal_progress_hud_nsn/ios`)
|
||||||
- package_info (from `.symlinks/plugins/package_info/ios`)
|
- package_info (from `.symlinks/plugins/package_info/ios`)
|
||||||
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
- path_provider (from `.symlinks/plugins/path_provider/ios`)
|
||||||
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
|
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
|
||||||
@ -220,7 +210,6 @@ SPEC REPOS:
|
|||||||
- FirebaseInstallations
|
- FirebaseInstallations
|
||||||
- FirebaseInstanceID
|
- FirebaseInstanceID
|
||||||
- FirebaseMessaging
|
- FirebaseMessaging
|
||||||
- Flurry-iOS-SDK
|
|
||||||
- FMDB
|
- FMDB
|
||||||
- GoogleAppMeasurement
|
- GoogleAppMeasurement
|
||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
@ -230,7 +219,6 @@ SPEC REPOS:
|
|||||||
- GTMSessionFetcher
|
- GTMSessionFetcher
|
||||||
- nanopb
|
- nanopb
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
- Protobuf
|
|
||||||
- Purchases
|
- Purchases
|
||||||
- PurchasesCoreSwift
|
- PurchasesCoreSwift
|
||||||
- PurchasesHybridCommon
|
- PurchasesHybridCommon
|
||||||
@ -238,8 +226,6 @@ SPEC REPOS:
|
|||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
apple_sign_in:
|
apple_sign_in:
|
||||||
:path: ".symlinks/plugins/apple_sign_in/ios"
|
:path: ".symlinks/plugins/apple_sign_in/ios"
|
||||||
audioplayer:
|
|
||||||
:path: ".symlinks/plugins/audioplayer/ios"
|
|
||||||
devicelocale:
|
devicelocale:
|
||||||
:path: ".symlinks/plugins/devicelocale/ios"
|
:path: ".symlinks/plugins/devicelocale/ios"
|
||||||
firebase_analytics:
|
firebase_analytics:
|
||||||
@ -250,18 +236,18 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_core/ios"
|
:path: ".symlinks/plugins/firebase_core/ios"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
flurry:
|
|
||||||
:path: ".symlinks/plugins/flurry/ios"
|
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
flutter_facebook_auth:
|
flutter_facebook_auth:
|
||||||
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
||||||
flutter_keyboard_visibility:
|
flutter_local_notifications:
|
||||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
:path: ".symlinks/plugins/flutter_secure_storage/ios"
|
||||||
google_sign_in:
|
google_sign_in:
|
||||||
:path: ".symlinks/plugins/google_sign_in/ios"
|
:path: ".symlinks/plugins/google_sign_in/ios"
|
||||||
|
modal_progress_hud_nsn:
|
||||||
|
:path: ".symlinks/plugins/modal_progress_hud_nsn/ios"
|
||||||
package_info:
|
package_info:
|
||||||
:path: ".symlinks/plugins/package_info/ios"
|
:path: ".symlinks/plugins/package_info/ios"
|
||||||
path_provider:
|
path_provider:
|
||||||
@ -284,52 +270,49 @@ EXTERNAL SOURCES:
|
|||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
AppAuth: 31bcec809a638d7bd2f86ea8a52bd45f6e81e7c7
|
||||||
apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4
|
apple_sign_in: 7716c7ddfa195aeab7dec0dc374ef4ff45d1adb4
|
||||||
audioplayer: 0584f31a697e4b0bbad405ae7903d7a93585e784
|
devicelocale: b22617f40038496deffba44747101255cee005b0
|
||||||
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
|
FBSDKCoreKit: a00fe2efd780c195a5e09201bf51c56106245b40
|
||||||
FBSDKCoreKit: ac6cc500b8e104bb9a4dd20b1527b5d199123c2e
|
FBSDKLoginKit: d98498c598ec09de657385a9349a1f21119b7f86
|
||||||
FBSDKLoginKit: e9b6542fdee322333502ab497f628b011dce7d78
|
Firebase: 26223c695fe322633274198cb19dca8cb7e54416
|
||||||
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
|
firebase_analytics: c9b8ddc8e864e45cd70761c5d972bd11c83574ab
|
||||||
firebase_analytics: 36a619088c46224900829f14f4daa71585693a6f
|
firebase_auth: 9f6491ea8e44570323361ae713a2ae3175b3f21a
|
||||||
firebase_auth: d5159db3873478d1ac839af7b10d2f831516136a
|
firebase_core: e6cbb0d1f7091edfcae31559e58224bfc1e455dc
|
||||||
firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659
|
firebase_messaging: 9c746d6c52bb05764e73bbe745d0d698e5afb695
|
||||||
firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75
|
FirebaseAnalytics: 2580c2d62535ae7b644143d48941fcc239ea897a
|
||||||
FirebaseAnalytics: 5dd088bd2e67bb9d13dbf792d1164ceaf3052193
|
FirebaseAuth: c224a0cf1afa0949bd5c7bfcf154b4f5ce8ddef2
|
||||||
FirebaseAuth: c92d49ada7948d1a23466e3db17bc4c2039dddc3
|
FirebaseCore: 4d3c72622ce0e2106aaa07bb4b2935ba2c370972
|
||||||
FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd
|
FirebaseCoreDiagnostics: d50e11039e5984d92c8a512be2395f13df747350
|
||||||
FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1
|
FirebaseInstallations: 5e777e6640fa060405cc7632447b6c5ca5af4742
|
||||||
FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2
|
FirebaseInstanceID: 53140c03b9f6136f890d7901399f85a4c90ab2d0
|
||||||
FirebaseInstanceID: bd3ffc24367f901a43c063b36c640b345a4a5dd1
|
FirebaseMessaging: 68d1bcb14880189558a8ae57167abe0b7e417232
|
||||||
FirebaseMessaging: 5eca4ef173de76253352511aafef774caa1cba2a
|
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
|
||||||
flurry: 15b01f664ab1367c62b50291541ea7f78ca85aad
|
flutter_facebook_auth: 4b170c07b7fce791497093fcc3f134fb215f3f07
|
||||||
Flurry-iOS-SDK: 6636d30c30f12010e7c7c71d84b443416a168efc
|
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
|
||||||
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
|
|
||||||
flutter_facebook_auth: d952ca599c6a76439c54472b0b225004e1b880c4
|
|
||||||
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
|
|
||||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||||
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
|
||||||
google_sign_in: 6bd214b9c154f881422f5fe27b66aaa7bbd580cc
|
google_sign_in: 6bd214b9c154f881422f5fe27b66aaa7bbd580cc
|
||||||
GoogleAppMeasurement: 966e88df9d19c15715137bb2ddaf52373f111436
|
GoogleAppMeasurement: 8d3c0aeede16ab7764144b5a4ca8e1d4323841b7
|
||||||
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
|
GoogleDataTransport: 116c84c4bdeb76be2a7a46de51244368f9794eab
|
||||||
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
|
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
|
||||||
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
|
GoogleUtilities: e1d9ed4e544fc32a93e00e721400cbc3f377200d
|
||||||
GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9
|
GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9
|
||||||
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
|
GTMSessionFetcher: b3503b20a988c4e20cc189aa798fd18220133f52
|
||||||
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
|
modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde
|
||||||
|
nanopb: 1bf24dd71191072e120b83dd02d08f3da0d65e53
|
||||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||||
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
|
||||||
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
|
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
|
||||||
Protobuf: 0cde852566359049847168e51bd1c690e0f70056
|
Purchases: 520fdb59140fed96932a30d02a3ec04858cb541c
|
||||||
Purchases: d8a798c9c7552fe66b550bf314a143e94ffa70c8
|
purchases_flutter: 05472ba84c83f05a138a3a657f1013f5f7143539
|
||||||
purchases_flutter: c1ef4056da1346795a708bdefce81e0a56e8134f
|
PurchasesCoreSwift: 31c2a3d7394432abbe64d46f0933835de0b33033
|
||||||
PurchasesCoreSwift: ea4eabae180416e580ac60366f41aa1fefec0693
|
PurchasesHybridCommon: 013c8072b73e752a206779747e88c068fbf999ec
|
||||||
PurchasesHybridCommon: d9bfb34309db4c9ba82a6f7f3a6275c13befdca7
|
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
||||||
smartlook: bda0b1561935a02ef0fea5448258d5ac75027859
|
smartlook: bda0b1561935a02ef0fea5448258d5ac75027859
|
||||||
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
|
||||||
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
|
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
|
||||||
wakelock: bfc7955c418d0db797614075aabbc58a39ab5107
|
wakelock: b0843b2479edbf6504d8d262c2959446f35373aa
|
||||||
webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
|
webview_flutter: 9f491a9b5a66f2573946a389b2677987b0ff8c0b
|
||||||
|
|
||||||
PODFILE CHECKSUM: ffdd26129895d158b3c89ac44e19a7e054386b90
|
PODFILE CHECKSUM: f10c0438b63bc24e6bbc207956dc27d16c4408f2
|
||||||
|
|
||||||
COCOAPODS: 1.10.0
|
COCOAPODS: 1.10.1
|
||||||
|
@ -2,10 +2,9 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class TestProgress extends AnimatedWidget {
|
class TestProgress extends AnimatedWidget {
|
||||||
|
|
||||||
TestProgress({
|
TestProgress({
|
||||||
Key key,
|
Key? key,
|
||||||
@required Animation<double> animation,
|
required Animation<double> animation,
|
||||||
}) : super(key: key, listenable: animation);
|
}) : super(key: key, listenable: animation);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -15,14 +14,14 @@ class TestProgress extends AnimatedWidget {
|
|||||||
return Transform.scale(
|
return Transform.scale(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
scale: animation.value,
|
scale: animation.value,
|
||||||
origin: Offset(-5,0),
|
origin: Offset(-5, 0),
|
||||||
child: Container(
|
child: Container(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
padding: EdgeInsets.only(left: 0),
|
padding: EdgeInsets.only(left: 0),
|
||||||
child: Icon(Icons.star, color: Colors.yellow,)
|
child: Icon(
|
||||||
),
|
Icons.star,
|
||||||
|
color: Colors.yellow,
|
||||||
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -16,9 +16,9 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
|||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
bool loggedIn = false;
|
bool loggedIn = false;
|
||||||
int traineeId = 0;
|
int traineeId = 0;
|
||||||
AccountBloc({this.customerRepository}) : super(AccountInitial()) {
|
AccountBloc({required this.customerRepository}) : super(AccountInitial()) {
|
||||||
if (Cache().userLoggedIn != null) {
|
if (Cache().userLoggedIn != null) {
|
||||||
customerRepository.customer = Cache().userLoggedIn;
|
customerRepository.customer = Cache().userLoggedIn!;
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
|||||||
yield AccountLoggedIn();
|
yield AccountLoggedIn();
|
||||||
} else if (event is AccountLogout) {
|
} else if (event is AccountLogout) {
|
||||||
await Cache().logout();
|
await Cache().logout();
|
||||||
customerRepository.customer = null;
|
//customerRepository.customer = null;
|
||||||
customerRepository.emptyTrainees();
|
customerRepository.emptyTrainees();
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
yield AccountLoggedOut();
|
yield AccountLoggedOut();
|
||||||
@ -85,7 +85,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
|
|||||||
} else if (event is AccountSelectTrainee) {
|
} else if (event is AccountSelectTrainee) {
|
||||||
yield AccountLoading();
|
yield AccountLoading();
|
||||||
customerRepository.setTrainee(event.traineeId);
|
customerRepository.setTrainee(event.traineeId);
|
||||||
Cache().setTrainee(customerRepository.getTraineeById(event.traineeId));
|
Cache().setTrainee(customerRepository.getTraineeById(event.traineeId)!);
|
||||||
ExerciseRepository exerciseRepository = ExerciseRepository();
|
ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
await exerciseRepository.getExercisesByCustomer(event.traineeId);
|
await exerciseRepository.getExercisesByCustomer(event.traineeId);
|
||||||
this.traineeId = event.traineeId;
|
this.traineeId = event.traineeId;
|
||||||
|
@ -9,37 +9,21 @@ abstract class AccountEvent extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AccountChangeCustomer extends AccountEvent {
|
class AccountChangeCustomer extends AccountEvent {
|
||||||
final Customer customer;
|
const AccountChangeCustomer();
|
||||||
|
|
||||||
const AccountChangeCustomer({this.customer});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [customer];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountLogout extends AccountEvent {
|
class AccountLogout extends AccountEvent {
|
||||||
final Customer customer;
|
const AccountLogout();
|
||||||
|
|
||||||
const AccountLogout({this.customer});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [customer];
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountLogin extends AccountEvent {
|
class AccountLogin extends AccountEvent {
|
||||||
final Customer customer;
|
const AccountLogin();
|
||||||
|
|
||||||
const AccountLogin({this.customer});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [customer];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccountLogInFinished extends AccountEvent {
|
class AccountLogInFinished extends AccountEvent {
|
||||||
final Customer customer;
|
final Customer customer;
|
||||||
|
|
||||||
const AccountLogInFinished({this.customer});
|
const AccountLogInFinished({required this.customer});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [customer];
|
List<Object> get props => [customer];
|
||||||
@ -51,8 +35,8 @@ class AccountGetTrainees extends AccountEvent {
|
|||||||
|
|
||||||
class AccountSelectTrainee extends AccountEvent {
|
class AccountSelectTrainee extends AccountEvent {
|
||||||
final int traineeId;
|
final int traineeId;
|
||||||
const AccountSelectTrainee({this.traineeId});
|
const AccountSelectTrainee({required this.traineeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [traineeId];
|
List<Object> get props => [traineeId];
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class AccountLoggedIn extends AccountState {
|
|||||||
|
|
||||||
class AccountError extends AccountState {
|
class AccountError extends AccountState {
|
||||||
final String message;
|
final String message;
|
||||||
const AccountError({this.message});
|
const AccountError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -13,14 +13,14 @@ class BodyDevelopmentBloc extends Bloc<BodyDevelopmentEvent, BodyDevelopmentStat
|
|||||||
final WorkoutTreeRepository workoutTreeRepository;
|
final WorkoutTreeRepository workoutTreeRepository;
|
||||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
|
|
||||||
List<int> radarTicks = List();
|
List<int> radarTicks = [];
|
||||||
List<String> radarFeatures = List();
|
List<String> radarFeatures = [];
|
||||||
List<List<int>> radarData = List();
|
List<List<int>> radarData = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
BodyDevelopmentBloc({this.workoutTreeRepository}): super(BodyDevelopmentInitial());
|
BodyDevelopmentBloc({required this.workoutTreeRepository}) : super(BodyDevelopmentInitial());
|
||||||
|
|
||||||
Future<void> getData() async{
|
Future<void> getData() async {
|
||||||
radarTicks = [20, 40, 60, 80, 100];
|
radarTicks = [20, 40, 60, 80, 100];
|
||||||
radarFeatures = ["Mell", "Bicepsz", "Tricepsz", "Hát", "Váll"];
|
radarFeatures = ["Mell", "Bicepsz", "Tricepsz", "Hát", "Váll"];
|
||||||
radarData = [
|
radarData = [
|
||||||
|
@ -22,9 +22,8 @@ class BodyDevelopmentReady extends BodyDevelopmentState {
|
|||||||
|
|
||||||
class BodyDevelopmentError extends BodyDevelopmentState {
|
class BodyDevelopmentError extends BodyDevelopmentState {
|
||||||
final String message;
|
final String message;
|
||||||
const BodyDevelopmentError({this.message});
|
const BodyDevelopmentError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ part 'bodytype_state.dart';
|
|||||||
class BodytypeBloc extends Bloc<BodytypeEvent, BodytypeState> {
|
class BodytypeBloc extends Bloc<BodytypeEvent, BodytypeState> {
|
||||||
static const int numberQuestions = 22;
|
static const int numberQuestions = 22;
|
||||||
final CustomerRepository repository;
|
final CustomerRepository repository;
|
||||||
final List<String> questions = List();
|
final List<String> questions = [];
|
||||||
final List<int> answers = List();
|
final List<int> answers = [];
|
||||||
final weights = List.generate(numberQuestions, (i) => List(3), growable: false);
|
final weights = List.generate(numberQuestions, (i) => []..length = 3, growable: false);
|
||||||
|
|
||||||
BodytypeBloc({this.repository}) : super(BodytypeInitial()) {
|
BodytypeBloc({required this.repository}) : super(BodytypeInitial()) {
|
||||||
questions.add("1. Basicly I am skinny and bonny");
|
questions.add("1. Basicly I am skinny and bonny");
|
||||||
questions.add("2. question");
|
questions.add("2. question");
|
||||||
questions.add("3. question");
|
questions.add("3. question");
|
||||||
@ -71,15 +71,14 @@ class BodytypeBloc extends Bloc<BodytypeEvent, BodytypeState> {
|
|||||||
weights[21] = [7, 3, 0];
|
weights[21] = [7, 3, 0];
|
||||||
|
|
||||||
final double value = repository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr());
|
final double value = repository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr());
|
||||||
if (value != null) {
|
|
||||||
_ecto = value.toInt();
|
_ecto = value.toInt();
|
||||||
_mezo = repository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
_mezo = repository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
||||||
_endo = repository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt();
|
_endo = repository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt();
|
||||||
print("** Init ecto: " + _ecto.toString() + " mezo: " + _mezo.toString() + " endo: " + _endo.toString());
|
print("** Init ecto: " + _ecto.toString() + " mezo: " + _mezo.toString() + " endo: " + _endo.toString());
|
||||||
if (_ecto > 0 && _mezo > 0 && _endo > 0) {
|
if (_ecto > 0 && _mezo > 0 && _endo > 0) {
|
||||||
calculateBodyType(init: true);
|
calculateBodyType(init: true);
|
||||||
origBodyTypeValue = bodyTypeValue;
|
origBodyTypeValue = bodyTypeValue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,13 +134,13 @@ class BodytypeBloc extends Bloc<BodytypeEvent, BodytypeState> {
|
|||||||
|
|
||||||
Future<void> savePropertyDB(String name, double value) async {
|
Future<void> savePropertyDB(String name, double value) async {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
Property property = repository.propertyRepository.getPropertyByName(name);
|
Property? property = repository.propertyRepository.getPropertyByName(name);
|
||||||
if (property != null) {
|
if (property != null) {
|
||||||
int propertyId = property.propertyId;
|
int propertyId = property.propertyId;
|
||||||
CustomerProperty customerProperty = repository.getCustomerProperty(name);
|
CustomerProperty? customerProperty = repository.getCustomerProperty(name);
|
||||||
if (customerProperty == null || customerProperty.customerPropertyId == null) {
|
if (customerProperty == null || customerProperty.customerPropertyId == null) {
|
||||||
customerProperty =
|
customerProperty =
|
||||||
CustomerProperty(customerId: Cache().userLoggedIn.customerId, propertyId: propertyId, propertyValue: value, dateAdd: now);
|
CustomerProperty(customerId: Cache().userLoggedIn!.customerId!, propertyId: propertyId, propertyValue: value, dateAdd: now);
|
||||||
|
|
||||||
CustomerProperty newProperty = await CustomerApi().addProperty(customerProperty);
|
CustomerProperty newProperty = await CustomerApi().addProperty(customerProperty);
|
||||||
repository.setCustomerProperty(name, value, id: newProperty.customerPropertyId);
|
repository.setCustomerProperty(name, value, id: newProperty.customerPropertyId);
|
||||||
|
@ -17,7 +17,7 @@ class BodytypeSave extends BodytypeEvent {
|
|||||||
|
|
||||||
class BodytypeClick extends BodytypeEvent {
|
class BodytypeClick extends BodytypeEvent {
|
||||||
final int value;
|
final int value;
|
||||||
const BodytypeClick({this.value});
|
const BodytypeClick({required this.value});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value];
|
List<Object> get props => [value];
|
||||||
|
@ -25,7 +25,7 @@ class BodytypeFinished extends BodytypeState {
|
|||||||
|
|
||||||
class BodytypeError extends BodytypeState {
|
class BodytypeError extends BodytypeState {
|
||||||
final String error;
|
final String error;
|
||||||
const BodytypeError({this.error});
|
const BodytypeError({required this.error});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [error];
|
List<Object> get props => [error];
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
import 'dart:math';
|
|
||||||
import 'package:aitrainer_app/repository/exercise_repository.dart';
|
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
|
||||||
|
|
||||||
class CustomExerciseFormBloc extends FormBloc<String, String> {
|
|
||||||
final ExerciseRepository exerciseRepository;
|
|
||||||
bool loading = false;
|
|
||||||
final quantityField = TextFieldBloc(
|
|
||||||
validators: [
|
|
||||||
FieldBlocValidators.required,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
final unitQuantityField = TextFieldBloc(
|
|
||||||
validators: [
|
|
||||||
FieldBlocValidators.required,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
//1RM calculated Fields
|
|
||||||
final rmWendlerField = TextFieldBloc(
|
|
||||||
initialValue: "0",
|
|
||||||
);
|
|
||||||
final rmMayhewField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rmOconnerField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rmWathenField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rmAverageField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm90Field = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm80Field = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm75Field = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm75WendlerField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm75OconnorField = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm70Field = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm60Field = TextFieldBloc(initialValue: "0");
|
|
||||||
final rm50Field = TextFieldBloc(initialValue: "0");
|
|
||||||
|
|
||||||
CustomExerciseFormBloc({this.exerciseRepository}) {
|
|
||||||
addFieldBlocs(fieldBlocs: [
|
|
||||||
quantityField,
|
|
||||||
unitQuantityField,
|
|
||||||
rmWendlerField,
|
|
||||||
rmMayhewField,
|
|
||||||
rmOconnerField,
|
|
||||||
rmWathenField,
|
|
||||||
rmAverageField,
|
|
||||||
rm90Field,
|
|
||||||
rm80Field,
|
|
||||||
rm70Field,
|
|
||||||
rm75Field,
|
|
||||||
rm75WendlerField,
|
|
||||||
rm75OconnorField,
|
|
||||||
rm60Field,
|
|
||||||
rm50Field
|
|
||||||
]);
|
|
||||||
|
|
||||||
quantityField.onValueChanges(onData: (previous, current) async* {
|
|
||||||
exerciseRepository.setQuantity(current.valueToDouble);
|
|
||||||
calculate1RM();
|
|
||||||
});
|
|
||||||
|
|
||||||
unitQuantityField.onValueChanges(onData: (previous, current) async* {
|
|
||||||
exerciseRepository.setUnitQuantity(current.valueToDouble);
|
|
||||||
calculate1RM();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onSubmitting() async {
|
|
||||||
try {
|
|
||||||
loading = true;
|
|
||||||
emitLoading(progress: 30);
|
|
||||||
// Emit either Loaded or Error
|
|
||||||
|
|
||||||
emitSuccess(canSubmitAgain: false);
|
|
||||||
loading = false;
|
|
||||||
} on Exception catch (ex) {
|
|
||||||
emitFailure(failureResponse: ex.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void calculate1RM() {
|
|
||||||
double weight = exerciseRepository.exercise.unitQuantity;
|
|
||||||
double repeat = exerciseRepository.exercise.quantity;
|
|
||||||
if (weight == 0 || repeat == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
exerciseRepository.rmWendler = weight * repeat * 0.0333 + weight;
|
|
||||||
rmWendlerField.updateValue(exerciseRepository.rmWendler.toStringAsFixed(1));
|
|
||||||
exerciseRepository.rmOconner = weight * (1 + repeat / 40);
|
|
||||||
rmOconnerField.updateValue(exerciseRepository.rmOconner.toStringAsFixed(1));
|
|
||||||
exerciseRepository.rmMayhew = 100 * weight / (52.2 + 41.9 * pow(e, -0.055 * repeat));
|
|
||||||
rmMayhewField.updateValue(exerciseRepository.rmMayhew.toStringAsFixed(1));
|
|
||||||
exerciseRepository.rmWathen = 100 * weight / (48.8 + 53.8 * pow(e, -0.075 * repeat));
|
|
||||||
rmWathenField.updateValue(exerciseRepository.rmWathen.toStringAsFixed(1));
|
|
||||||
double average = (exerciseRepository.rmWendler + exerciseRepository.rmOconner) / 2;
|
|
||||||
rmAverageField.updateValue(average.toStringAsFixed(1));
|
|
||||||
rm90Field.updateValue((average * 0.9).toStringAsFixed(1));
|
|
||||||
rm80Field.updateValue((average * 0.8).toStringAsFixed(1));
|
|
||||||
rm75Field.updateValue((average * 0.75).toStringAsFixed(1));
|
|
||||||
rm75OconnorField.updateValue((exerciseRepository.rmOconner * 0.75).toStringAsFixed(1));
|
|
||||||
rm75WendlerField.updateValue((exerciseRepository.rmWendler * 0.75).toStringAsFixed(1));
|
|
||||||
rm70Field.updateValue((average * 0.7).toStringAsFixed(1));
|
|
||||||
rm60Field.updateValue((average * 0.6).toStringAsFixed(1));
|
|
||||||
rm50Field.updateValue((average * 0.5).toStringAsFixed(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
//@override
|
|
||||||
Future<void> close() {
|
|
||||||
quantityField.close();
|
|
||||||
unitQuantityField.close();
|
|
||||||
|
|
||||||
rmWendlerField.close();
|
|
||||||
rmMayhewField.close();
|
|
||||||
rmOconnerField.close();
|
|
||||||
rmWathenField.close();
|
|
||||||
rmAverageField.close();
|
|
||||||
rm90Field.close();
|
|
||||||
rm80Field.close();
|
|
||||||
rm75WendlerField.close();
|
|
||||||
rm75OconnorField.close();
|
|
||||||
rm75Field.close();
|
|
||||||
rm70Field.close();
|
|
||||||
rm60Field.close();
|
|
||||||
rm50Field.close();
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,14 +14,13 @@ part 'customer_change_state.dart';
|
|||||||
|
|
||||||
class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState> with Trans {
|
class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState> with Trans {
|
||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
final BuildContext context;
|
|
||||||
bool visiblePassword = false;
|
bool visiblePassword = false;
|
||||||
int year = 1990;
|
int? year = 1990;
|
||||||
double weight = 60;
|
double weight = 60;
|
||||||
double height = 170;
|
double height = 170;
|
||||||
CustomerChangeBloc({this.customerRepository, this.context}) : super(CustomerChangeInitial()) {
|
CustomerChangeBloc({required this.customerRepository}) : super(CustomerChangeInitial()) {
|
||||||
year = this.customerRepository.customer.birthYear;
|
year = this.customerRepository.customer.birthYear;
|
||||||
if (year == 0) {
|
if (year == null || year == 0) {
|
||||||
year = 1990;
|
year = 1990;
|
||||||
}
|
}
|
||||||
weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight();
|
weight = this.customerRepository.getWeight() == 0 ? 60 : this.customerRepository.getWeight();
|
||||||
@ -102,23 +101,23 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
|
|||||||
(nameValidation(customerRepository.customer.name) == null); */
|
(nameValidation(customerRepository.customer.name) == null); */
|
||||||
}
|
}
|
||||||
|
|
||||||
String emailValidation(String email) {
|
String? emailValidation(String email) {
|
||||||
String message = Common.emailValidation(email);
|
String? message = Common.emailValidation(email);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
message = t(message);
|
message = t(message);
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
String passwordValidation(String value) {
|
String? passwordValidation(String value) {
|
||||||
String message = Common.passwordValidation(value);
|
String? message = Common.passwordValidation(value);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
message = t(message);
|
message = t(message);
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
String nameValidation(String value) {
|
String? nameValidation(String? value) {
|
||||||
if (value == null || value.length == 0) {
|
if (value == null || value.length == 0) {
|
||||||
return t("Name too short");
|
return t("Name too short");
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ abstract class CustomerChangeEvent extends Equatable {
|
|||||||
|
|
||||||
class CustomerGoalChange extends CustomerChangeEvent {
|
class CustomerGoalChange extends CustomerChangeEvent {
|
||||||
final String goal;
|
final String goal;
|
||||||
const CustomerGoalChange({this.goal});
|
const CustomerGoalChange({required this.goal});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [goal];
|
List<Object> get props => [goal];
|
||||||
@ -17,7 +17,7 @@ class CustomerGoalChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerFitnessChange extends CustomerChangeEvent {
|
class CustomerFitnessChange extends CustomerChangeEvent {
|
||||||
final String fitness;
|
final String fitness;
|
||||||
const CustomerFitnessChange({this.fitness});
|
const CustomerFitnessChange({required this.fitness});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [fitness];
|
List<Object> get props => [fitness];
|
||||||
@ -25,7 +25,7 @@ class CustomerFitnessChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerBodyTypeChange extends CustomerChangeEvent {
|
class CustomerBodyTypeChange extends CustomerChangeEvent {
|
||||||
final String bodyType;
|
final String bodyType;
|
||||||
const CustomerBodyTypeChange({this.bodyType});
|
const CustomerBodyTypeChange({required this.bodyType});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [bodyType];
|
List<Object> get props => [bodyType];
|
||||||
@ -33,7 +33,7 @@ class CustomerBodyTypeChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerBirthYearChange extends CustomerChangeEvent {
|
class CustomerBirthYearChange extends CustomerChangeEvent {
|
||||||
final int year;
|
final int year;
|
||||||
const CustomerBirthYearChange({this.year});
|
const CustomerBirthYearChange({required this.year});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [year];
|
List<Object> get props => [year];
|
||||||
@ -41,7 +41,7 @@ class CustomerBirthYearChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerWeightChange extends CustomerChangeEvent {
|
class CustomerWeightChange extends CustomerChangeEvent {
|
||||||
final int weight;
|
final int weight;
|
||||||
const CustomerWeightChange({this.weight});
|
const CustomerWeightChange({required this.weight});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [weight];
|
List<Object> get props => [weight];
|
||||||
@ -49,7 +49,7 @@ class CustomerWeightChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerHeightChange extends CustomerChangeEvent {
|
class CustomerHeightChange extends CustomerChangeEvent {
|
||||||
final int height;
|
final int height;
|
||||||
const CustomerHeightChange({this.height});
|
const CustomerHeightChange({required this.height});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [height];
|
List<Object> get props => [height];
|
||||||
@ -57,7 +57,7 @@ class CustomerHeightChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerGenderChange extends CustomerChangeEvent {
|
class CustomerGenderChange extends CustomerChangeEvent {
|
||||||
final int gender;
|
final int gender;
|
||||||
const CustomerGenderChange({this.gender});
|
const CustomerGenderChange({required this.gender});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [gender];
|
List<Object> get props => [gender];
|
||||||
@ -65,7 +65,7 @@ class CustomerGenderChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerEmailChange extends CustomerChangeEvent {
|
class CustomerEmailChange extends CustomerChangeEvent {
|
||||||
final String email;
|
final String email;
|
||||||
const CustomerEmailChange({this.email});
|
const CustomerEmailChange({required this.email});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email];
|
List<Object> get props => [email];
|
||||||
@ -73,7 +73,7 @@ class CustomerEmailChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerFirstNameChange extends CustomerChangeEvent {
|
class CustomerFirstNameChange extends CustomerChangeEvent {
|
||||||
final String firstName;
|
final String firstName;
|
||||||
const CustomerFirstNameChange({this.firstName});
|
const CustomerFirstNameChange({required this.firstName});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [firstName];
|
List<Object> get props => [firstName];
|
||||||
@ -81,7 +81,7 @@ class CustomerFirstNameChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerNameChange extends CustomerChangeEvent {
|
class CustomerNameChange extends CustomerChangeEvent {
|
||||||
final String name;
|
final String name;
|
||||||
const CustomerNameChange({this.name});
|
const CustomerNameChange({required this.name});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [name];
|
List<Object> get props => [name];
|
||||||
@ -89,7 +89,7 @@ class CustomerNameChange extends CustomerChangeEvent {
|
|||||||
|
|
||||||
class CustomerPasswordChange extends CustomerChangeEvent {
|
class CustomerPasswordChange extends CustomerChangeEvent {
|
||||||
final String password;
|
final String password;
|
||||||
const CustomerPasswordChange({this.password});
|
const CustomerPasswordChange({required this.password});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [password];
|
List<Object> get props => [password];
|
||||||
|
@ -29,7 +29,7 @@ class CustomerSaveSuccess extends CustomerChangeState {
|
|||||||
|
|
||||||
class CustomerSaveError extends CustomerChangeState {
|
class CustomerSaveError extends CustomerChangeState {
|
||||||
final String message;
|
final String message;
|
||||||
const CustomerSaveError({this.message});
|
const CustomerSaveError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -13,11 +13,11 @@ part 'customer_exercise_device_state.dart';
|
|||||||
|
|
||||||
class CustomerExerciseDeviceBloc extends Bloc<CustomerExerciseDeviceEvent, CustomerExerciseDeviceState> {
|
class CustomerExerciseDeviceBloc extends Bloc<CustomerExerciseDeviceEvent, CustomerExerciseDeviceState> {
|
||||||
final CustomerExerciseDeviceRepository repository;
|
final CustomerExerciseDeviceRepository repository;
|
||||||
final List<ExerciseDevice> devices;
|
final List<ExerciseDevice>? devices;
|
||||||
|
|
||||||
CustomerExerciseDeviceBloc({this.repository, this.devices}) : super(CustomerExerciseDeviceInitial()) {
|
CustomerExerciseDeviceBloc({required this.repository, required this.devices}) : super(CustomerExerciseDeviceInitial()) {
|
||||||
if (repository.getDevices().isEmpty) {
|
if (repository.getDevices().isEmpty) {
|
||||||
repository.setDevices(Cache().getCustomerDevices());
|
repository.setDevices(Cache().getCustomerDevices()!);
|
||||||
}
|
}
|
||||||
Track().track(TrackingEvent.exercise_device);
|
Track().track(TrackingEvent.exercise_device);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class CustomerExerciseDeviceLoad extends CustomerExerciseDeviceEvent {
|
|||||||
|
|
||||||
class CustomerExerciseDeviceAdd extends CustomerExerciseDeviceEvent {
|
class CustomerExerciseDeviceAdd extends CustomerExerciseDeviceEvent {
|
||||||
final ExerciseDevice device;
|
final ExerciseDevice device;
|
||||||
const CustomerExerciseDeviceAdd({this.device});
|
const CustomerExerciseDeviceAdd({required this.device});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [device];
|
List<Object> get props => [device];
|
||||||
@ -21,7 +21,7 @@ class CustomerExerciseDeviceAdd extends CustomerExerciseDeviceEvent {
|
|||||||
|
|
||||||
class CustomerExerciseDeviceRemove extends CustomerExerciseDeviceEvent {
|
class CustomerExerciseDeviceRemove extends CustomerExerciseDeviceEvent {
|
||||||
final ExerciseDevice device;
|
final ExerciseDevice device;
|
||||||
const CustomerExerciseDeviceRemove({this.device});
|
const CustomerExerciseDeviceRemove({required this.device});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [device];
|
List<Object> get props => [device];
|
||||||
|
@ -21,7 +21,7 @@ class CustomerExerciseDeviceReady extends CustomerExerciseDeviceState {
|
|||||||
|
|
||||||
class CustomerExerciseDeviceError extends CustomerExerciseDeviceState {
|
class CustomerExerciseDeviceError extends CustomerExerciseDeviceState {
|
||||||
final String message;
|
final String message;
|
||||||
const CustomerExerciseDeviceError({this.message});
|
const CustomerExerciseDeviceError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -13,11 +13,10 @@ import 'package:aitrainer_app/util/common.dart';
|
|||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/group_data.dart';
|
import 'package:aitrainer_app/util/group_data.dart';
|
||||||
import 'package:aitrainer_app/util/track.dart';
|
import 'package:aitrainer_app/util/track.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
|
|
||||||
@ -36,35 +35,35 @@ class DiagramType {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class GroupDate extends GroupData with Calculate, Common {
|
class GroupDate extends GroupData with Calculate, Common {
|
||||||
final List<dynamic> inputList;
|
final List<Exercise> inputList;
|
||||||
final List<dynamic> outputList;
|
final List<Exercise> outputList;
|
||||||
|
|
||||||
String _origDatePart;
|
String? _origDatePart;
|
||||||
int _origExerciseTypeId;
|
late int _origExerciseTypeId;
|
||||||
Exercise _origExercise;
|
late Exercise _origExercise;
|
||||||
|
|
||||||
double _sumQuantity;
|
late double _sumQuantity;
|
||||||
double _maxQuantity;
|
late double _maxQuantity;
|
||||||
int _countExercises;
|
late int _countExercises;
|
||||||
|
|
||||||
String diagramType;
|
late String diagramType;
|
||||||
String dateRate;
|
late String dateRate;
|
||||||
|
|
||||||
GroupDate({this.inputList, this.outputList});
|
GroupDate({required this.inputList, required this.outputList});
|
||||||
|
|
||||||
double getQuantityByDate(Exercise exercise) {
|
double getQuantityByDate(Exercise exercise) {
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
if (this.diagramType == DiagramType.sumMass) {
|
if (this.diagramType == DiagramType.sumMass) {
|
||||||
if (exercise.unitQuantity != null) {
|
if (exercise.unitQuantity != null) {
|
||||||
sum = exercise.quantity * exercise.unitQuantity;
|
sum = exercise.quantity! * exercise.unitQuantity!;
|
||||||
} else {
|
} else {
|
||||||
sum = exercise.quantity;
|
sum = exercise.quantity!;
|
||||||
}
|
}
|
||||||
} else if (this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent) {
|
} else if (this.diagramType == DiagramType.oneRepMax || this.diagramType == DiagramType.percent) {
|
||||||
if (exercise.unitQuantity != null) {
|
if (exercise.unitQuantity != null) {
|
||||||
sum = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
sum = calculate1RM(exercise.quantity!, exercise.unitQuantity!);
|
||||||
} else {
|
} else {
|
||||||
sum = exercise.quantity;
|
sum = exercise.quantity!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
@ -73,26 +72,26 @@ class GroupDate extends GroupData with Calculate, Common {
|
|||||||
@override
|
@override
|
||||||
void addTempData(Exercise exercise) {
|
void addTempData(Exercise exercise) {
|
||||||
double newQuantity = getQuantityByDate(exercise);
|
double newQuantity = getQuantityByDate(exercise);
|
||||||
_sumQuantity += newQuantity;
|
_sumQuantity = _sumQuantity + newQuantity;
|
||||||
if (_maxQuantity < newQuantity) {
|
if (_maxQuantity < newQuantity) {
|
||||||
_maxQuantity = newQuantity;
|
_maxQuantity = newQuantity;
|
||||||
}
|
}
|
||||||
_countExercises++;
|
_countExercises = _countExercises + 1;
|
||||||
_origDatePart = getDatePart(exercise.dateAdd, dateRate);
|
_origDatePart = getDatePart(exercise.dateAdd!, dateRate);
|
||||||
_origExerciseTypeId = exercise.exerciseTypeId;
|
_origExerciseTypeId = exercise.exerciseTypeId!;
|
||||||
_origExercise = exercise;
|
_origExercise = exercise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool checkNewType(Exercise exercise) {
|
bool checkNewType(Exercise exercise) {
|
||||||
String exerciseDatePart = getDatePart(exercise.dateAdd, dateRate);
|
String exerciseDatePart = getDatePart(exercise.dateAdd!, dateRate);
|
||||||
return _origDatePart != exerciseDatePart || _origExerciseTypeId != exercise.exerciseTypeId;
|
return _origDatePart == null || _origDatePart != exerciseDatePart || _origExerciseTypeId != exercise.exerciseTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void iteration() {
|
void iteration() {
|
||||||
this.resetTemp();
|
this.resetTemp();
|
||||||
Exercise tempExercise;
|
Exercise? tempExercise;
|
||||||
inputList.forEach((element) {
|
inputList.forEach((element) {
|
||||||
tempExercise = element;
|
tempExercise = element;
|
||||||
if (this.checkNewType(element)) {
|
if (this.checkNewType(element)) {
|
||||||
@ -108,7 +107,7 @@ class GroupDate extends GroupData with Calculate, Common {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tempExercise != null) {
|
if (tempExercise != null) {
|
||||||
this.temp2Output(tempExercise);
|
this.temp2Output(tempExercise!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,21 +141,21 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
final List<dynamic> inputList;
|
final List<dynamic> inputList;
|
||||||
LinkedHashMap<int, ChartDataExtended> outputList = LinkedHashMap();
|
LinkedHashMap<int, ChartDataExtended> outputList = LinkedHashMap();
|
||||||
|
|
||||||
int _origExerciseTypeId;
|
int? _origExerciseTypeId;
|
||||||
double _minData = 999999999999;
|
late double _minData = 999999999999;
|
||||||
double _maxData = 0;
|
late double _maxData = 0;
|
||||||
List<BarChartGroupData> _chartData;
|
late List<BarChartGroupData> _chartData;
|
||||||
double _basePercent;
|
late double _basePercent;
|
||||||
|
|
||||||
String diagramType = DiagramType.sumMass;
|
String diagramType = DiagramType.sumMass;
|
||||||
|
|
||||||
GroupChart({this.inputList, this.outputList});
|
GroupChart({required this.inputList, required this.outputList});
|
||||||
|
|
||||||
double getBasePercent(Exercise exercise) {
|
double getBasePercent(Exercise exercise) {
|
||||||
if (exercise.unitQuantity != null) {
|
if (exercise.unitQuantity != null) {
|
||||||
this._basePercent = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
this._basePercent = calculate1RM(exercise.quantity!, exercise.unitQuantity!);
|
||||||
} else {
|
} else {
|
||||||
this._basePercent = exercise.quantity;
|
this._basePercent = exercise.quantity!;
|
||||||
}
|
}
|
||||||
return this._basePercent;
|
return this._basePercent;
|
||||||
}
|
}
|
||||||
@ -166,13 +165,13 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
|
|
||||||
if (diagramType == DiagramType.percent) {
|
if (diagramType == DiagramType.percent) {
|
||||||
if (exercise.unitQuantity != null) {
|
if (exercise.unitQuantity != null) {
|
||||||
double oneRepMax = calculate1RM(exercise.quantity, exercise.unitQuantity);
|
double oneRepMax = calculate1RM(exercise.quantity!, exercise.unitQuantity!);
|
||||||
value = (oneRepMax / this._basePercent) * 100;
|
value = (oneRepMax / this._basePercent) * 100;
|
||||||
} else {
|
} else {
|
||||||
value = (exercise.quantity / this._basePercent) * 100;
|
value = (exercise.quantity! / this._basePercent) * 100;
|
||||||
}
|
}
|
||||||
} else if (diagramType == DiagramType.oneRepMax || diagramType == DiagramType.sumMass) {
|
} else if (diagramType == DiagramType.oneRepMax || diagramType == DiagramType.sumMass) {
|
||||||
value = exercise.calculated;
|
value = exercise.calculated!;
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -188,22 +187,22 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
_minData = diagramValue;
|
_minData = diagramValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BarChartGroupData data = BarChartGroupData(x: exercise.dateAdd.millisecondsSinceEpoch, barRods: [
|
BarChartGroupData data = BarChartGroupData(x: exercise.dateAdd!.millisecondsSinceEpoch, barRods: [
|
||||||
BarChartRodData(y: diagramValue, width: 12, colors: [Colors.lightBlue, Colors.lightBlueAccent])
|
BarChartRodData(y: diagramValue, width: 12, colors: [Colors.lightBlue, Colors.lightBlueAccent])
|
||||||
]);
|
]);
|
||||||
_chartData.add(data);
|
_chartData.add(data);
|
||||||
_origExerciseTypeId = exercise.exerciseTypeId;
|
_origExerciseTypeId = exercise.exerciseTypeId!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool checkNewType(Exercise exercise) {
|
bool checkNewType(Exercise exercise) {
|
||||||
return _origExerciseTypeId != exercise.exerciseTypeId;
|
return _origExerciseTypeId == null || _origExerciseTypeId != exercise.exerciseTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void iteration() {
|
void iteration() {
|
||||||
this.resetTemp();
|
this.resetTemp();
|
||||||
Exercise tempExercise;
|
Exercise? tempExercise;
|
||||||
inputList.forEach((element) {
|
inputList.forEach((element) {
|
||||||
tempExercise = element;
|
tempExercise = element;
|
||||||
|
|
||||||
@ -222,7 +221,7 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (tempExercise != null) {
|
if (tempExercise != null) {
|
||||||
this.temp2Output(tempExercise);
|
this.temp2Output(tempExercise!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,9 +233,9 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
ChartDataExtended extended;
|
ChartDataExtended extended;
|
||||||
if (outputList[_origExerciseTypeId] == null) {
|
if (outputList[_origExerciseTypeId] == null) {
|
||||||
extended = ChartDataExtended(data: _chartData, interval: dInterval, gridInterval: gridInterval);
|
extended = ChartDataExtended(data: _chartData, interval: dInterval, gridInterval: gridInterval);
|
||||||
outputList[_origExerciseTypeId] = extended;
|
outputList[_origExerciseTypeId!] = extended;
|
||||||
} else {
|
} else {
|
||||||
extended = outputList[_origExerciseTypeId];
|
extended = outputList[_origExerciseTypeId]!;
|
||||||
_chartData.forEach((element) {
|
_chartData.forEach((element) {
|
||||||
extended.data.add(element);
|
extended.data.add(element);
|
||||||
});
|
});
|
||||||
@ -247,7 +246,7 @@ class GroupChart extends GroupData with Calculate {
|
|||||||
void resetTemp() {
|
void resetTemp() {
|
||||||
_minData = 999999999999;
|
_minData = 999999999999;
|
||||||
_maxData = 0;
|
_maxData = 0;
|
||||||
_chartData = List();
|
_chartData = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,10 +255,10 @@ class ChartDataExtended {
|
|||||||
final double interval;
|
final double interval;
|
||||||
final int gridInterval;
|
final int gridInterval;
|
||||||
|
|
||||||
const ChartDataExtended({this.data, this.interval, this.gridInterval});
|
const ChartDataExtended({required this.data, required this.interval, required this.gridInterval});
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
List listBarChartData = List();
|
List listBarChartData = [];
|
||||||
data.forEach((element) {
|
data.forEach((element) {
|
||||||
element.barRods.forEach((rods) {
|
element.barRods.forEach((rods) {
|
||||||
var barChartData = {
|
var barChartData = {
|
||||||
@ -280,18 +279,19 @@ class ChartDataExtended {
|
|||||||
|
|
||||||
class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, DevelopmentByMuscleState> with Calculate, Logging {
|
class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, DevelopmentByMuscleState> with Calculate, Logging {
|
||||||
final WorkoutTreeRepository workoutTreeRepository;
|
final WorkoutTreeRepository workoutTreeRepository;
|
||||||
|
|
||||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap();
|
LinkedHashMap<int, ChartDataExtended> listChartData = LinkedHashMap();
|
||||||
List<BarChartGroupData> chartData;
|
late List<BarChartGroupData> chartData;
|
||||||
String diagramType = DiagramType.sumMass;
|
String diagramType = DiagramType.sumMass;
|
||||||
String dateRate = DateRate.daily;
|
String dateRate = DateRate.daily;
|
||||||
double basePercent = 0;
|
double basePercent = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
DevelopmentByMuscleBloc({this.workoutTreeRepository}) : super(DevelopmentByMuscleStateInitial());
|
DevelopmentByMuscleBloc({required this.workoutTreeRepository}) : super(DevelopmentByMuscleStateInitial());
|
||||||
|
|
||||||
Future<void> getData() async {
|
Future<void> getData() async {
|
||||||
workoutTreeRepository.sortedTree = null;
|
workoutTreeRepository.sortedTree.clear();
|
||||||
workoutTreeRepository.sortByMuscleType();
|
workoutTreeRepository.sortByMuscleType();
|
||||||
|
|
||||||
workoutTreeRepository.sortedTree.forEach((key, value) {
|
workoutTreeRepository.sortedTree.forEach((key, value) {
|
||||||
@ -305,7 +305,7 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getChartData() {
|
void getChartData() {
|
||||||
List<Exercise> exercises = exerciseRepository.getExerciseList();
|
List<Exercise>? exercises = exerciseRepository.getExerciseList();
|
||||||
|
|
||||||
//print("-- Start calculate --- ");
|
//print("-- Start calculate --- ");
|
||||||
exercises = this.groupByDate(exercises);
|
exercises = this.groupByDate(exercises);
|
||||||
@ -322,24 +322,25 @@ class DevelopmentByMuscleBloc extends Bloc<DevelopmentByMuscleEvent, Development
|
|||||||
listChartData = groupChart.outputList;
|
listChartData = groupChart.outputList;
|
||||||
|
|
||||||
listChartData.forEach((key, value) {
|
listChartData.forEach((key, value) {
|
||||||
trace("typeid " + key.toString() + " chardata " + value.toJson().toString());
|
//trace("typeid " + key.toString() + " chardata " + value.toJson().toString());
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Exercise> groupByDate(List<Exercise> exercises) {
|
List<Exercise> groupByDate(List<Exercise>? exercises) {
|
||||||
List<Exercise> groupedExercises = List();
|
List<Exercise> groupedExercises = [];
|
||||||
|
if (exercises != null) {
|
||||||
|
exercises = sort(exercises, false);
|
||||||
|
exercises.forEach((exercise) {
|
||||||
|
//trace("Date exercise " + exercise.toJsonDatePart().toString());
|
||||||
|
});
|
||||||
|
|
||||||
exercises = sort(exercises, false);
|
GroupDate groupDate = GroupDate(inputList: exercises, outputList: groupedExercises);
|
||||||
exercises.forEach((exercise) {
|
groupDate.dateRate = this.dateRate;
|
||||||
trace("Date exercise " + exercise.toJsonDatePart().toString());
|
groupDate.diagramType = this.diagramType;
|
||||||
});
|
groupDate.iteration();
|
||||||
|
groupedExercises = groupDate.outputList;
|
||||||
GroupDate groupDate = GroupDate(inputList: exercises, outputList: groupedExercises);
|
}
|
||||||
groupDate.dateRate = this.dateRate;
|
|
||||||
groupDate.diagramType = this.diagramType;
|
|
||||||
groupDate.iteration();
|
|
||||||
groupedExercises = groupDate.outputList;
|
|
||||||
|
|
||||||
/* groupedExercises.forEach((element) {
|
/* groupedExercises.forEach((element) {
|
||||||
print("Grouped " + element.toJsonDatePart().toString());
|
print("Grouped " + element.toJsonDatePart().toString());
|
||||||
|
@ -14,7 +14,7 @@ class DevelopmentByMuscleLoad extends DevelopmentByMuscleEvent {
|
|||||||
|
|
||||||
class DevelopmentByMuscleDateRateChange extends DevelopmentByMuscleEvent {
|
class DevelopmentByMuscleDateRateChange extends DevelopmentByMuscleEvent {
|
||||||
final String dateRate;
|
final String dateRate;
|
||||||
const DevelopmentByMuscleDateRateChange({this.dateRate});
|
const DevelopmentByMuscleDateRateChange({required this.dateRate});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [dateRate];
|
List<Object> get props => [dateRate];
|
||||||
@ -22,7 +22,7 @@ class DevelopmentByMuscleDateRateChange extends DevelopmentByMuscleEvent {
|
|||||||
|
|
||||||
class DevelopmentByMuscleDiagramTypeChange extends DevelopmentByMuscleEvent {
|
class DevelopmentByMuscleDiagramTypeChange extends DevelopmentByMuscleEvent {
|
||||||
final String diagramType;
|
final String diagramType;
|
||||||
const DevelopmentByMuscleDiagramTypeChange({this.diagramType});
|
const DevelopmentByMuscleDiagramTypeChange({required this.diagramType});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [diagramType];
|
List<Object> get props => [diagramType];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
part of 'development_by_muscle_bloc.dart';
|
part of 'development_by_muscle_bloc.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
abstract class DevelopmentByMuscleState extends Equatable{
|
abstract class DevelopmentByMuscleState extends Equatable {
|
||||||
const DevelopmentByMuscleState();
|
const DevelopmentByMuscleState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -20,10 +20,9 @@ class DevelopmentByMuscleReadyState extends DevelopmentByMuscleState {
|
|||||||
const DevelopmentByMuscleReadyState();
|
const DevelopmentByMuscleReadyState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentByMuscleErrorState extends DevelopmentByMuscleState {
|
class DevelopmentByMuscleErrorState extends DevelopmentByMuscleState {
|
||||||
final String message;
|
final String message;
|
||||||
const DevelopmentByMuscleErrorState({this.message});
|
const DevelopmentByMuscleErrorState({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -10,11 +10,11 @@ part 'development_sizes_state.dart';
|
|||||||
|
|
||||||
class DevelopmentSizesBloc extends Bloc<DevelopmentSizesEvent, DevelopmentSizesState> {
|
class DevelopmentSizesBloc extends Bloc<DevelopmentSizesEvent, DevelopmentSizesState> {
|
||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
DevelopmentSizesBloc({this.customerRepository}) : super(DevelopmentSizesInitial()) {
|
DevelopmentSizesBloc({required this.customerRepository}) : super(DevelopmentSizesInitial()) {
|
||||||
isMan = Cache().userLoggedIn.sex == "m";
|
isMan = Cache().userLoggedIn!.sex == "m";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMan;
|
late bool isMan;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<DevelopmentSizesState> mapEventToState(
|
Stream<DevelopmentSizesState> mapEventToState(
|
||||||
|
@ -21,7 +21,7 @@ class DevelopmentSizesReady extends DevelopmentSizesState {
|
|||||||
|
|
||||||
class DevelopmentSizesError extends DevelopmentSizesState {
|
class DevelopmentSizesError extends DevelopmentSizesState {
|
||||||
final String message;
|
final String message;
|
||||||
const DevelopmentSizesError({this.message});
|
const DevelopmentSizesError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [this.message];
|
List<Object> get props => [this.message];
|
||||||
|
@ -15,23 +15,24 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
final bool readonly;
|
final bool readonly;
|
||||||
int step = 1;
|
int step = 1;
|
||||||
|
|
||||||
double initialRM;
|
late double initialRM;
|
||||||
double unitQuantity;
|
late double unitQuantity;
|
||||||
double quantity;
|
late double quantity;
|
||||||
double origQuantity;
|
late double origQuantity;
|
||||||
double oneRepQuantity;
|
late double oneRepQuantity;
|
||||||
double oneRepUnitQuantity;
|
late double oneRepUnitQuantity;
|
||||||
|
|
||||||
double firstQuantity; // quantity of the first test
|
double? firstQuantity; // quantity of the first test
|
||||||
double firstUnitQuantity; // unit quantity of the first test
|
double? firstUnitQuantity; // unit quantity of the first test
|
||||||
|
|
||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseControlBloc({this.exerciseRepository, this.readonly, @required this.timerBloc}) : super(ExerciseControlInitial()) {
|
ExerciseControlBloc({required this.exerciseRepository, required this.readonly, required this.timerBloc})
|
||||||
print("Exercise ${exerciseRepository.exercise.toJson()}");
|
: super(ExerciseControlInitial()) {
|
||||||
oneRepQuantity = exerciseRepository.exercise.quantity;
|
print("Exercise ${exerciseRepository.exercise!.toJson()}");
|
||||||
oneRepUnitQuantity = exerciseRepository.exercise.unitQuantity;
|
oneRepQuantity = exerciseRepository.exercise!.quantity!;
|
||||||
|
oneRepUnitQuantity = exerciseRepository.exercise!.unitQuantity!;
|
||||||
initialRM = this.calculate1RM(percent75: false);
|
initialRM = this.calculate1RM(percent75: false);
|
||||||
unitQuantity = this.calculate1RM(percent75: true).roundToDouble();
|
unitQuantity = this.calculate1RM(percent75: true).roundToDouble();
|
||||||
quantity = 12;
|
quantity = 12;
|
||||||
@ -76,14 +77,14 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
scrollOffset = step * 400.0;
|
scrollOffset = step * 400.0;
|
||||||
|
|
||||||
quantity = origQuantity;
|
quantity = origQuantity;
|
||||||
if (exerciseRepository.exercise.quantity == null) {
|
if (exerciseRepository.exercise!.quantity == null) {
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
}
|
}
|
||||||
exerciseRepository.end = DateTime.now();
|
exerciseRepository.end = DateTime.now();
|
||||||
await exerciseRepository.addExercise();
|
await exerciseRepository.addExercise();
|
||||||
//exerciseRepository.initExercise();
|
//exerciseRepository.initExercise();
|
||||||
|
|
||||||
step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd());
|
step <= 3 ? timerBloc.add(TimerStart(duration: 300)) : timerBloc.add(TimerEnd(duration: 300));
|
||||||
}
|
}
|
||||||
yield ExerciseControlReady();
|
yield ExerciseControlReady();
|
||||||
}
|
}
|
||||||
@ -92,12 +93,12 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double calculate1RM({bool percent75}) {
|
double calculate1RM({bool percent75 = true}) {
|
||||||
if (exerciseRepository.exercise == null) {
|
if (exerciseRepository.exercise == null) {
|
||||||
exerciseRepository.getLastExercise();
|
exerciseRepository.getLastExercise();
|
||||||
}
|
}
|
||||||
double weight = exerciseRepository.exercise.unitQuantity;
|
double weight = exerciseRepository.exercise!.unitQuantity!;
|
||||||
double repeat = exerciseRepository.exercise.quantity;
|
double repeat = exerciseRepository.exercise!.quantity!;
|
||||||
if (weight == 0 || repeat == 0) {
|
if (weight == 0 || repeat == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -117,8 +118,8 @@ class ExerciseControlBloc extends Bloc<ExerciseControlEvent, ExerciseControlStat
|
|||||||
final double rmOconner = weight * (1 + repeat / 40);
|
final double rmOconner = weight * (1 + repeat / 40);
|
||||||
print("Weight: $weight oneRepQuantity: $repeat, $rmWendler, Oconner: $rmOconner");
|
print("Weight: $weight oneRepQuantity: $repeat, $rmWendler, Oconner: $rmOconner");
|
||||||
|
|
||||||
weight = exerciseRepository.exercise.unitQuantity;
|
weight = exerciseRepository.exercise!.unitQuantity!;
|
||||||
repeat = exerciseRepository.exercise.quantity;
|
repeat = exerciseRepository.exercise!.quantity!;
|
||||||
|
|
||||||
final double repeatWendler = (rmWendler - weight) / 0.0333 / weight;
|
final double repeatWendler = (rmWendler - weight) / 0.0333 / weight;
|
||||||
final double repeatOconner = (rmOconner / weight - 1) * 40;
|
final double repeatOconner = (rmOconner / weight - 1) * 40;
|
||||||
|
@ -15,16 +15,16 @@ class ExerciseControlLoad extends ExerciseControlEvent {
|
|||||||
class ExerciseControlQuantityChange extends ExerciseControlEvent {
|
class ExerciseControlQuantityChange extends ExerciseControlEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
final int step;
|
final int step;
|
||||||
const ExerciseControlQuantityChange({this.quantity, this.step});
|
const ExerciseControlQuantityChange({required this.quantity, required this.step});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExerciseControlUnitQuantityChange extends ExerciseControlEvent {
|
class ExerciseControlUnitQuantityChange extends ExerciseControlEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
final int step;
|
final int step;
|
||||||
const ExerciseControlUnitQuantityChange({this.quantity, this.step});
|
const ExerciseControlUnitQuantityChange({required this.quantity, required this.step});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExerciseControlSubmit extends ExerciseControlEvent {
|
class ExerciseControlSubmit extends ExerciseControlEvent {
|
||||||
final int step;
|
final int step;
|
||||||
const ExerciseControlSubmit({this.step});
|
const ExerciseControlSubmit({required this.step});
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,8 @@ class ExerciseControlReady extends ExerciseControlState {
|
|||||||
|
|
||||||
class ExerciseControlError extends ExerciseControlState {
|
class ExerciseControlError extends ExerciseControlState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExerciseControlError({this.message});
|
const ExerciseControlError({required this.message});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -14,16 +14,17 @@ part 'exercise_execute_plan_state.dart';
|
|||||||
class ExerciseExecutePlanBloc extends Bloc<ExerciseExecutePlanEvent, ExerciseExecutePlanState> {
|
class ExerciseExecutePlanBloc extends Bloc<ExerciseExecutePlanEvent, ExerciseExecutePlanState> {
|
||||||
final WorkoutTreeRepository menuTreeRepository;
|
final WorkoutTreeRepository menuTreeRepository;
|
||||||
final ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
final ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
||||||
int customerId;
|
int? customerId;
|
||||||
int selectedNumber = 0;
|
int selectedNumber = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseExecutePlanBloc({this.menuTreeRepository}) : super(ExerciseByPlanStateInitial());
|
ExerciseExecutePlanBloc({required this.menuTreeRepository}) : super(ExerciseByPlanStateInitial());
|
||||||
|
|
||||||
Future<void> getData() async {
|
Future<void> getData() async {
|
||||||
exercisePlanRepository.setCustomerId(customerId);
|
exercisePlanRepository.setCustomerId(customerId!);
|
||||||
await exercisePlanRepository.getLastExercisePlan();
|
await exercisePlanRepository.getLastExercisePlan();
|
||||||
await exercisePlanRepository.getExercisePlanDetails();
|
await exercisePlanRepository.getExercisePlanDetails();
|
||||||
menuTreeRepository.sortedTree = null;
|
menuTreeRepository.sortedTree.clear();
|
||||||
menuTreeRepository.sortByMuscleType();
|
menuTreeRepository.sortByMuscleType();
|
||||||
|
|
||||||
menuTreeRepository.sortedTree.forEach((key, value) {
|
menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
|
@ -10,7 +10,7 @@ abstract class ExerciseExecutePlanEvent extends Equatable {
|
|||||||
|
|
||||||
class AddExerciseByPlanEvent extends ExerciseExecutePlanEvent {
|
class AddExerciseByPlanEvent extends ExerciseExecutePlanEvent {
|
||||||
final ExerciseType exerciseType;
|
final ExerciseType exerciseType;
|
||||||
const AddExerciseByPlanEvent({this.exerciseType});
|
const AddExerciseByPlanEvent({required this.exerciseType});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseType];
|
List<Object> get props => [exerciseType];
|
||||||
|
@ -24,8 +24,8 @@ class ExerciseByPlanReady extends ExerciseExecutePlanState {
|
|||||||
// error splash screen
|
// error splash screen
|
||||||
class ExerciseByPlanError extends ExerciseExecutePlanState {
|
class ExerciseByPlanError extends ExerciseExecutePlanState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExerciseByPlanError({this.message});
|
const ExerciseByPlanError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -22,30 +22,35 @@ class ExerciseExecutePlanAddBloc extends Bloc<ExerciseExecutePlanAddEvent, Exerc
|
|||||||
final ExerciseExecutePlanBloc planBloc;
|
final ExerciseExecutePlanBloc planBloc;
|
||||||
final int customerId;
|
final int customerId;
|
||||||
|
|
||||||
Customer customer;
|
late Customer customer;
|
||||||
int step = 1;
|
int step = 1;
|
||||||
int countSteps = 1;
|
int countSteps = 1;
|
||||||
|
|
||||||
double quantity;
|
late double quantity;
|
||||||
double unitQuantity;
|
late double unitQuantity;
|
||||||
|
|
||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseExecutePlanAddBloc({this.exerciseRepository, this.exercisePlanRepository, this.customerId, this.workoutTree, this.planBloc})
|
ExerciseExecutePlanAddBloc(
|
||||||
|
{required this.exerciseRepository,
|
||||||
|
required this.exercisePlanRepository,
|
||||||
|
required this.customerId,
|
||||||
|
required this.workoutTree,
|
||||||
|
required this.planBloc})
|
||||||
: super(ExerciseExecutePlanAddInitial()) {
|
: super(ExerciseExecutePlanAddInitial()) {
|
||||||
exerciseRepository.exerciseType = workoutTree.exerciseType;
|
exerciseRepository.exerciseType = workoutTree.exerciseType;
|
||||||
if (Cache().userLoggedIn.customerId == customerId) {
|
if (Cache().userLoggedIn!.customerId == customerId) {
|
||||||
customer = Cache().userLoggedIn;
|
customer = Cache().userLoggedIn!;
|
||||||
} else if (Cache().getTrainee().customerId == customerId) {
|
} else if (Cache().getTrainee()!.customerId == customerId) {
|
||||||
customer = Cache().getTrainee();
|
customer = Cache().getTrainee()!;
|
||||||
}
|
}
|
||||||
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType);
|
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType!);
|
||||||
exerciseRepository.customer = customer;
|
exerciseRepository.customer = customer;
|
||||||
countSteps = exercisePlanRepository.getActualPlanDetail().serie;
|
countSteps = exercisePlanRepository.getActualPlanDetail()!.serie!;
|
||||||
|
|
||||||
unitQuantity = double.parse(exercisePlanRepository.getActualPlanDetail().weightEquation);
|
unitQuantity = double.parse(exercisePlanRepository.getActualPlanDetail()!.weightEquation!);
|
||||||
quantity = exercisePlanRepository.getActualPlanDetail().repeats.toDouble();
|
quantity = exercisePlanRepository.getActualPlanDetail()!.repeats!.toDouble();
|
||||||
|
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||||
@ -70,8 +75,8 @@ class ExerciseExecutePlanAddBloc extends Bloc<ExerciseExecutePlanAddEvent, Exerc
|
|||||||
yield ExerciseExecutePlanAddReady();
|
yield ExerciseExecutePlanAddReady();
|
||||||
} else if (event is ExerciseExecutePlanAddSubmit) {
|
} else if (event is ExerciseExecutePlanAddSubmit) {
|
||||||
yield ExerciseExecutePlanAddLoading();
|
yield ExerciseExecutePlanAddLoading();
|
||||||
exerciseRepository.exercise.exercisePlanDetailId = exercisePlanRepository.getActualPlanDetail().exercisePlanDetailId;
|
exerciseRepository.exercise!.exercisePlanDetailId = exercisePlanRepository.getActualPlanDetail()!.exercisePlanDetailId;
|
||||||
exerciseRepository.exercise.unit = workoutTree.exerciseType.unit;
|
exerciseRepository.exercise!.unit = workoutTree.exerciseType!.unit;
|
||||||
workoutTree.executed = true;
|
workoutTree.executed = true;
|
||||||
await exerciseRepository.addExercise();
|
await exerciseRepository.addExercise();
|
||||||
exerciseRepository.initExercise();
|
exerciseRepository.initExercise();
|
||||||
|
@ -14,7 +14,7 @@ class ExerciseExecutePlanAddLoad extends ExerciseExecutePlanAddEvent {
|
|||||||
|
|
||||||
class ExerciseExecutePlanAddChangeQuantity extends ExerciseExecutePlanAddEvent {
|
class ExerciseExecutePlanAddChangeQuantity extends ExerciseExecutePlanAddEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExerciseExecutePlanAddChangeQuantity({this.quantity});
|
const ExerciseExecutePlanAddChangeQuantity({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -22,7 +22,7 @@ class ExerciseExecutePlanAddChangeQuantity extends ExerciseExecutePlanAddEvent {
|
|||||||
|
|
||||||
class ExerciseExecutePlanAddChangeUnitQuantity extends ExerciseExecutePlanAddEvent {
|
class ExerciseExecutePlanAddChangeUnitQuantity extends ExerciseExecutePlanAddEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExerciseExecutePlanAddChangeUnitQuantity({this.quantity});
|
const ExerciseExecutePlanAddChangeUnitQuantity({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
|
@ -24,8 +24,8 @@ class ExerciseExecutePlanAddReady extends ExerciseExecutePlanAddState {
|
|||||||
// error splash screen
|
// error splash screen
|
||||||
class ExerciseExecutePlanAddError extends ExerciseExecutePlanAddState {
|
class ExerciseExecutePlanAddError extends ExerciseExecutePlanAddState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExerciseExecutePlanAddError({this.message});
|
const ExerciseExecutePlanAddError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ part 'exercise_log_state.dart';
|
|||||||
class ExerciseLogBloc extends Bloc<ExerciseLogEvent, ExerciseLogState> {
|
class ExerciseLogBloc extends Bloc<ExerciseLogEvent, ExerciseLogState> {
|
||||||
final ExerciseRepository exerciseRepository;
|
final ExerciseRepository exerciseRepository;
|
||||||
@override
|
@override
|
||||||
ExerciseLogBloc({this.exerciseRepository}) : super(ExerciseLogInitial());
|
ExerciseLogBloc({required this.exerciseRepository}) : super(ExerciseLogInitial());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<ExerciseLogState> mapEventToState(ExerciseLogEvent event) async* {
|
Stream<ExerciseLogState> mapEventToState(ExerciseLogEvent event) async* {
|
||||||
@ -27,7 +27,7 @@ class ExerciseLogBloc extends Bloc<ExerciseLogEvent, ExerciseLogState> {
|
|||||||
yield ExerciseLogReady();
|
yield ExerciseLogReady();
|
||||||
} else if (event is ExerciseLogDelete) {
|
} else if (event is ExerciseLogDelete) {
|
||||||
yield ExerciseLogLoading();
|
yield ExerciseLogLoading();
|
||||||
exerciseRepository.exerciseList.remove(event.exercise);
|
exerciseRepository.exerciseList!.remove(event.exercise);
|
||||||
await exerciseRepository.deleteExercise(event.exercise);
|
await exerciseRepository.deleteExercise(event.exercise);
|
||||||
Track().track(TrackingEvent.exercise_log_delete);
|
Track().track(TrackingEvent.exercise_log_delete);
|
||||||
yield ExerciseLogReady();
|
yield ExerciseLogReady();
|
||||||
|
@ -14,7 +14,7 @@ class ExerciseLogLoad extends ExerciseLogEvent {
|
|||||||
|
|
||||||
class ExerciseLogDelete extends ExerciseLogEvent {
|
class ExerciseLogDelete extends ExerciseLogEvent {
|
||||||
final Exercise exercise;
|
final Exercise exercise;
|
||||||
const ExerciseLogDelete({this.exercise});
|
const ExerciseLogDelete({required this.exercise});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exercise];
|
List<Object> get props => [exercise];
|
||||||
|
@ -22,9 +22,8 @@ class ExerciseLogReady extends ExerciseLogState {
|
|||||||
|
|
||||||
class ExerciseLogError extends ExerciseLogState {
|
class ExerciseLogError extends ExerciseLogState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExerciseLogError({this.message});
|
const ExerciseLogError({required this.message});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
|
||||||
import 'package:aitrainer_app/model/cache.dart';
|
import 'package:aitrainer_app/model/cache.dart';
|
||||||
import 'package:aitrainer_app/model/exercise_type.dart';
|
import 'package:aitrainer_app/model/exercise_type.dart';
|
||||||
@ -12,7 +14,6 @@ import 'package:bloc/bloc.dart';
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/animation.dart';
|
import 'package:flutter/animation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
import 'package:stop_watch_timer/stop_watch_timer.dart';
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
final ExerciseRepository exerciseRepository;
|
final ExerciseRepository exerciseRepository;
|
||||||
final CustomerRepository customerRepository;
|
final CustomerRepository customerRepository;
|
||||||
final MenuBloc menuBloc;
|
final MenuBloc menuBloc;
|
||||||
AnimationController bmiAnimationController;
|
late AnimationController bmiAnimationController;
|
||||||
double quantity = 12;
|
double quantity = 12;
|
||||||
double unitQuantity = 30;
|
double unitQuantity = 30;
|
||||||
double bmi = 0;
|
double bmi = 0;
|
||||||
@ -35,11 +36,11 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
double bmiAngle = 0;
|
double bmiAngle = 0;
|
||||||
double bmiTop = 0;
|
double bmiTop = 0;
|
||||||
double bmiLeft = 0;
|
double bmiLeft = 0;
|
||||||
double weight;
|
late double weight;
|
||||||
double height;
|
late double height;
|
||||||
double bmrEnergy = 0;
|
double bmrEnergy = 0;
|
||||||
int birthYear;
|
late int birthYear;
|
||||||
String fitnessLevel;
|
late String fitnessLevel;
|
||||||
bool changedWeight = false;
|
bool changedWeight = false;
|
||||||
bool changedSizes = false;
|
bool changedSizes = false;
|
||||||
|
|
||||||
@ -53,23 +54,24 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
final StopWatchTimer stopWatchTimer = StopWatchTimer(
|
final StopWatchTimer stopWatchTimer = StopWatchTimer(
|
||||||
isLapHours: false,
|
isLapHours: false,
|
||||||
);
|
);
|
||||||
int timerValue;
|
late int timerValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExerciseNewBloc({this.exerciseRepository, this.menuBloc, this.customerRepository, ExerciseType exerciseType})
|
ExerciseNewBloc(
|
||||||
|
{required this.exerciseRepository, required this.menuBloc, required this.customerRepository, required ExerciseType exerciseType})
|
||||||
: super(ExerciseNewInitial()) {
|
: super(ExerciseNewInitial()) {
|
||||||
exerciseRepository.exerciseType = exerciseType;
|
exerciseRepository.exerciseType = exerciseType;
|
||||||
exerciseRepository.setUnit(exerciseType.unit);
|
exerciseRepository.setUnit(exerciseType.unit);
|
||||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
exerciseRepository.exercise.exercisePlanDetailId = 0;
|
exerciseRepository.exercise!.exercisePlanDetailId = 0;
|
||||||
exerciseRepository.start = DateTime.now();
|
exerciseRepository.start = DateTime.now();
|
||||||
if (Cache().userLoggedIn != null) {
|
if (Cache().userLoggedIn != null) {
|
||||||
customerRepository.customer = Cache().userLoggedIn;
|
customerRepository.customer = Cache().userLoggedIn!;
|
||||||
weight = customerRepository.customer.getProperty("Weight");
|
weight = customerRepository.customer.getProperty("Weight");
|
||||||
height = customerRepository.customer.getProperty("Height");
|
height = customerRepository.customer.getProperty("Height");
|
||||||
birthYear = customerRepository.customer.birthYear;
|
birthYear = customerRepository.customer.birthYear!;
|
||||||
fitnessLevel = customerRepository.customer.fitnessLevel;
|
fitnessLevel = customerRepository.customer.fitnessLevel!;
|
||||||
}
|
}
|
||||||
if (exerciseType.unit == "second") {
|
if (exerciseType.unit == "second") {
|
||||||
stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())});
|
stopWatchTimer.rawTime.listen((value) => {timerValue = value, this.setQuantity((value / 1000).toDouble())});
|
||||||
@ -151,7 +153,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
// exerciseRepository.initExercise();
|
// exerciseRepository.initExercise();
|
||||||
menuBloc.add(MenuTreeDown(parent: 0));
|
menuBloc.add(MenuTreeDown(parent: 0));
|
||||||
Cache().initBadges();
|
Cache().initBadges();
|
||||||
Track().track(TrackingEvent.exercise_new, eventValue: exerciseRepository.exerciseType.name);
|
Track().track(TrackingEvent.exercise_new, eventValue: exerciseRepository.exerciseType!.name);
|
||||||
yield ExerciseNewSaved();
|
yield ExerciseNewSaved();
|
||||||
} else if (event is ExerciseNewBMIAnimate) {
|
} else if (event is ExerciseNewBMIAnimate) {
|
||||||
yield ExerciseNewLoading();
|
yield ExerciseNewLoading();
|
||||||
@ -183,10 +185,10 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
|
|||||||
|
|
||||||
if (customerRepository.customer.sex == "m") {
|
if (customerRepository.customer.sex == "m") {
|
||||||
//66.47 + ( 13.75 × tömeg kg-ban ) + ( 5.003 × magasság cm-ben ) − ( 6.755 × életkor évben kifejezve )
|
//66.47 + ( 13.75 × tömeg kg-ban ) + ( 5.003 × magasság cm-ben ) − ( 6.755 × életkor évben kifejezve )
|
||||||
bmr = 66.47 + (13.75 * weight) + (5.003 * height) - (6.755 * (year - customerRepository.customer.birthYear));
|
bmr = 66.47 + (13.75 * weight) + (5.003 * height) - (6.755 * (year - customerRepository.customer.birthYear!));
|
||||||
} else {
|
} else {
|
||||||
//BMR = 655.1 + ( 9.563 × ömeg kg-ban ) + ( 1.85 × magasság cm-ben) − ( 4.676 × életkor évben kifejezve )
|
//BMR = 655.1 + ( 9.563 × ömeg kg-ban ) + ( 1.85 × magasság cm-ben) − ( 4.676 × életkor évben kifejezve )
|
||||||
bmr = 655.1 + (9.563 * weight) + (1.85 * height) - (4.676 * (year - customerRepository.customer.birthYear));
|
bmr = 655.1 + (9.563 * weight) + (1.85 * height) - (4.676 * (year - customerRepository.customer.birthYear!));
|
||||||
}
|
}
|
||||||
bmrEnergy = bmr;
|
bmrEnergy = bmr;
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class ExerciseNewLoad extends ExerciseNewEvent {
|
|||||||
|
|
||||||
class ExerciseNewQuantityChange extends ExerciseNewEvent {
|
class ExerciseNewQuantityChange extends ExerciseNewEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExerciseNewQuantityChange({this.quantity});
|
const ExerciseNewQuantityChange({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -22,7 +22,7 @@ class ExerciseNewQuantityChange extends ExerciseNewEvent {
|
|||||||
|
|
||||||
class ExerciseNewQuantityUnitChange extends ExerciseNewEvent {
|
class ExerciseNewQuantityUnitChange extends ExerciseNewEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExerciseNewQuantityUnitChange({this.quantity});
|
const ExerciseNewQuantityUnitChange({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -30,21 +30,21 @@ class ExerciseNewQuantityUnitChange extends ExerciseNewEvent {
|
|||||||
|
|
||||||
class ExerciseNewBirthyearChange extends ExerciseNewEvent {
|
class ExerciseNewBirthyearChange extends ExerciseNewEvent {
|
||||||
final int value;
|
final int value;
|
||||||
const ExerciseNewBirthyearChange({this.value});
|
const ExerciseNewBirthyearChange({required this.value});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value];
|
List<Object> get props => [value];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExerciseNewWeightChange extends ExerciseNewEvent {
|
class ExerciseNewWeightChange extends ExerciseNewEvent {
|
||||||
final double value;
|
final double value;
|
||||||
const ExerciseNewWeightChange({this.value});
|
const ExerciseNewWeightChange({required this.value});
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value];
|
List<Object> get props => [value];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExerciseNewHeightChange extends ExerciseNewEvent {
|
class ExerciseNewHeightChange extends ExerciseNewEvent {
|
||||||
final double value;
|
final double value;
|
||||||
const ExerciseNewHeightChange({this.value});
|
const ExerciseNewHeightChange({required this.value});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value];
|
List<Object> get props => [value];
|
||||||
@ -52,7 +52,7 @@ class ExerciseNewHeightChange extends ExerciseNewEvent {
|
|||||||
|
|
||||||
class ExerciseNewFitnessLevelChange extends ExerciseNewEvent {
|
class ExerciseNewFitnessLevelChange extends ExerciseNewEvent {
|
||||||
final String value;
|
final String value;
|
||||||
const ExerciseNewFitnessLevelChange({this.value});
|
const ExerciseNewFitnessLevelChange({required this.value});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [value];
|
List<Object> get props => [value];
|
||||||
@ -61,7 +61,7 @@ class ExerciseNewFitnessLevelChange extends ExerciseNewEvent {
|
|||||||
class ExerciseNewSizeChange extends ExerciseNewEvent {
|
class ExerciseNewSizeChange extends ExerciseNewEvent {
|
||||||
final String propertyName;
|
final String propertyName;
|
||||||
final double value;
|
final double value;
|
||||||
const ExerciseNewSizeChange({this.propertyName, this.value});
|
const ExerciseNewSizeChange({required this.propertyName, required this.value});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [propertyName, value];
|
List<Object> get props => [propertyName, value];
|
||||||
|
@ -26,7 +26,7 @@ class ExerciseNewSaved extends ExerciseNewState {
|
|||||||
|
|
||||||
class ExerciseNewError extends ExerciseNewState {
|
class ExerciseNewError extends ExerciseNewState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExerciseNewError({this.message});
|
const ExerciseNewError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -17,15 +17,15 @@ part 'exercise_plan_state.dart';
|
|||||||
class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
||||||
final WorkoutTreeRepository menuTreeRepository;
|
final WorkoutTreeRepository menuTreeRepository;
|
||||||
ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
ExercisePlanRepository exercisePlanRepository = ExercisePlanRepository();
|
||||||
int customerId;
|
late int customerId;
|
||||||
|
|
||||||
ExercisePlanBloc({this.menuTreeRepository}) : super(ExercisePlanInitial());
|
ExercisePlanBloc({required this.menuTreeRepository}) : super(ExercisePlanInitial());
|
||||||
|
|
||||||
Future<void> getData() async {
|
Future<void> getData() async {
|
||||||
exercisePlanRepository.setCustomerId(customerId);
|
exercisePlanRepository.setCustomerId(customerId);
|
||||||
await exercisePlanRepository.getLastExercisePlan();
|
await exercisePlanRepository.getLastExercisePlan();
|
||||||
await exercisePlanRepository.getExercisePlanDetails();
|
await exercisePlanRepository.getExercisePlanDetails();
|
||||||
menuTreeRepository.sortedTree = null;
|
menuTreeRepository.sortedTree.clear();
|
||||||
menuTreeRepository.sortByMuscleType();
|
menuTreeRepository.sortByMuscleType();
|
||||||
|
|
||||||
menuTreeRepository.sortedTree.forEach((key, value) {
|
menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
@ -33,7 +33,7 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
|||||||
listWorkoutTree.forEach((workoutTree) {
|
listWorkoutTree.forEach((workoutTree) {
|
||||||
workoutTree.selected = false;
|
workoutTree.selected = false;
|
||||||
if (exercisePlanRepository.getExercisePlanDetailSize() > 0) {
|
if (exercisePlanRepository.getExercisePlanDetailSize() > 0) {
|
||||||
ExercisePlanDetail planDetail = exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId);
|
ExercisePlanDetail? planDetail = exercisePlanRepository.getExercisePlanDetailByExerciseId(workoutTree.exerciseTypeId);
|
||||||
if (planDetail != null && planDetail.change != ModelChange.deleted) {
|
if (planDetail != null && planDetail.change != ModelChange.deleted) {
|
||||||
workoutTree.selected = true;
|
workoutTree.selected = true;
|
||||||
}
|
}
|
||||||
@ -58,10 +58,8 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
|||||||
yield ExercisePlanLoading();
|
yield ExercisePlanLoading();
|
||||||
|
|
||||||
WorkoutMenuTree workoutTree = event.workoutTree;
|
WorkoutMenuTree workoutTree = event.workoutTree;
|
||||||
if (workoutTree != null) {
|
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType!);
|
||||||
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutTree.exerciseType);
|
workoutTree.selected = true;
|
||||||
workoutTree.selected = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield ExercisePlanReady();
|
yield ExercisePlanReady();
|
||||||
} else if (event is ExercisePlanAddExercise) {
|
} else if (event is ExercisePlanAddExercise) {
|
||||||
@ -76,7 +74,7 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
|||||||
this.menuTreeRepository.sortedTree.forEach((key, value) {
|
this.menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
List<WorkoutMenuTree> listTreeItem = value;
|
List<WorkoutMenuTree> listTreeItem = value;
|
||||||
listTreeItem.forEach((element) {
|
listTreeItem.forEach((element) {
|
||||||
if (element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) {
|
if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
|
||||||
element.selected = true;
|
element.selected = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -91,7 +89,7 @@ class ExercisePlanBloc extends Bloc<ExercisePlanEvent, ExercisePlanState> {
|
|||||||
this.menuTreeRepository.sortedTree.forEach((key, value) {
|
this.menuTreeRepository.sortedTree.forEach((key, value) {
|
||||||
List<WorkoutMenuTree> listTreeItem = value;
|
List<WorkoutMenuTree> listTreeItem = value;
|
||||||
listTreeItem.forEach((element) {
|
listTreeItem.forEach((element) {
|
||||||
if (element.exerciseType.exerciseTypeId == planDetail.exerciseTypeId) {
|
if (element.exerciseType!.exerciseTypeId == planDetail.exerciseTypeId) {
|
||||||
element.selected = false;
|
element.selected = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -11,20 +11,18 @@ class ExercisePlanLoad extends ExercisePlanEvent {
|
|||||||
const ExercisePlanLoad();
|
const ExercisePlanLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// update UI
|
// update UI
|
||||||
class ExercisePlanUpdateUI extends ExercisePlanEvent {
|
class ExercisePlanUpdateUI extends ExercisePlanEvent {
|
||||||
final WorkoutMenuTree workoutTree;
|
final WorkoutMenuTree workoutTree;
|
||||||
const ExercisePlanUpdateUI({this.workoutTree});
|
const ExercisePlanUpdateUI({required this.workoutTree});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [workoutTree];
|
List<Object> get props => [workoutTree];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ExercisePlanRemoveExercise extends ExercisePlanEvent {
|
class ExercisePlanRemoveExercise extends ExercisePlanEvent {
|
||||||
final ExercisePlanDetail exercisePlanDetail;
|
final ExercisePlanDetail exercisePlanDetail;
|
||||||
const ExercisePlanRemoveExercise({this.exercisePlanDetail});
|
const ExercisePlanRemoveExercise({required this.exercisePlanDetail});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exercisePlanDetail];
|
List<Object> get props => [exercisePlanDetail];
|
||||||
@ -32,8 +30,8 @@ class ExercisePlanRemoveExercise extends ExercisePlanEvent {
|
|||||||
|
|
||||||
class ExercisePlanAddExercise extends ExercisePlanEvent {
|
class ExercisePlanAddExercise extends ExercisePlanEvent {
|
||||||
final ExercisePlanDetail exercisePlanDetail;
|
final ExercisePlanDetail exercisePlanDetail;
|
||||||
const ExercisePlanAddExercise({this.exercisePlanDetail});
|
const ExercisePlanAddExercise({required this.exercisePlanDetail});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exercisePlanDetail];
|
List<Object> get props => [exercisePlanDetail];
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
part of 'exercise_plan_bloc.dart';
|
part of 'exercise_plan_bloc.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
abstract class ExercisePlanState extends Equatable{
|
abstract class ExercisePlanState extends Equatable {
|
||||||
const ExercisePlanState();
|
const ExercisePlanState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -26,12 +26,8 @@ class ExercisePlanReady extends ExercisePlanState {
|
|||||||
// error splash screen
|
// error splash screen
|
||||||
class ExercisePlanError extends ExercisePlanState {
|
class ExercisePlanError extends ExercisePlanState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExercisePlanError({this.message});
|
const ExercisePlanError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,23 +22,30 @@ class ExercisePlanCustomAddBloc extends Bloc<ExercisePlanCustomAddEvent, Exercis
|
|||||||
final ExercisePlanBloc planBloc;
|
final ExercisePlanBloc planBloc;
|
||||||
final WorkoutMenuTree workoutMenuTree;
|
final WorkoutMenuTree workoutMenuTree;
|
||||||
|
|
||||||
double quantity;
|
late double quantity;
|
||||||
double serie;
|
double? serie;
|
||||||
double quantityUnit;
|
late double quantityUnit;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ExercisePlanCustomAddBloc({this.exercisePlanRepository, this.planBloc, this.workoutMenuTree}) : super(ExercisePlanCustomAddInitial()) {
|
ExercisePlanCustomAddBloc({required this.exercisePlanRepository, required this.planBloc, required this.workoutMenuTree})
|
||||||
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutMenuTree.exerciseType);
|
: super(ExercisePlanCustomAddInitial()) {
|
||||||
quantity =
|
// init();
|
||||||
exercisePlanRepository.getActualPlanDetail().repeats != null ? exercisePlanRepository.getActualPlanDetail().repeats.toDouble() : 12;
|
}
|
||||||
serie = exercisePlanRepository.getActualPlanDetail().serie != null ? exercisePlanRepository.getActualPlanDetail().serie.toDouble() : 3;
|
|
||||||
quantityUnit = exercisePlanRepository.getActualPlanDetail().weightEquation != null
|
void init() {
|
||||||
? double.parse(exercisePlanRepository.getActualPlanDetail().weightEquation)
|
exercisePlanRepository.setActualPlanDetailByExerciseType(workoutMenuTree.exerciseType!);
|
||||||
|
quantity = exercisePlanRepository.getActualPlanDetail()!.repeats != null
|
||||||
|
? exercisePlanRepository.getActualPlanDetail()!.repeats!.toDouble()
|
||||||
|
: 12;
|
||||||
|
serie =
|
||||||
|
exercisePlanRepository.getActualPlanDetail()!.serie != null ? exercisePlanRepository.getActualPlanDetail()!.serie!.toDouble() : 3;
|
||||||
|
quantityUnit = exercisePlanRepository.getActualPlanDetail()!.weightEquation != null
|
||||||
|
? double.parse(exercisePlanRepository.getActualPlanDetail()!.weightEquation!)
|
||||||
: 30;
|
: 30;
|
||||||
|
|
||||||
exercisePlanRepository.getActualPlanDetail().weightEquation = quantityUnit.toString();
|
exercisePlanRepository.getActualPlanDetail()!.weightEquation = quantityUnit.toString();
|
||||||
exercisePlanRepository.getActualPlanDetail().serie = serie.toInt();
|
exercisePlanRepository.getActualPlanDetail()!.serie = serie!.toInt();
|
||||||
exercisePlanRepository.getActualPlanDetail().repeats = quantity.toInt();
|
exercisePlanRepository.getActualPlanDetail()!.repeats = quantity.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -46,36 +53,37 @@ class ExercisePlanCustomAddBloc extends Bloc<ExercisePlanCustomAddEvent, Exercis
|
|||||||
try {
|
try {
|
||||||
if (event is ExercisePlanCustomAddLoad) {
|
if (event is ExercisePlanCustomAddLoad) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
|
init();
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
} else if (event is ExercisePlanCustomAddChangeSerie) {
|
} else if (event is ExercisePlanCustomAddChangeSerie) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
serie = event.quantity;
|
serie = event.quantity;
|
||||||
exercisePlanRepository.getActualPlanDetail().serie = event.quantity.toInt();
|
exercisePlanRepository.getActualPlanDetail()!.serie = event.quantity.toInt();
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
} else if (event is ExercisePlanCustomAddChangeQuantity) {
|
} else if (event is ExercisePlanCustomAddChangeQuantity) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
quantity = event.quantity;
|
quantity = event.quantity;
|
||||||
exercisePlanRepository.getActualPlanDetail().repeats = event.quantity.toInt();
|
exercisePlanRepository.getActualPlanDetail()!.repeats = event.quantity.toInt();
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
} else if (event is ExercisePlanCustomAddChangeQuantityUnit) {
|
} else if (event is ExercisePlanCustomAddChangeQuantityUnit) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
quantityUnit = event.quantity;
|
quantityUnit = event.quantity;
|
||||||
exercisePlanRepository.getActualPlanDetail().weightEquation = event.quantity.toStringAsFixed(0);
|
exercisePlanRepository.getActualPlanDetail()!.weightEquation = event.quantity.toStringAsFixed(0);
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
} else if (event is ExercisePlanCustomAddSubmit) {
|
} else if (event is ExercisePlanCustomAddSubmit) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
if (exercisePlanRepository.exercisePlanDetails[exercisePlanRepository.getActualPlanDetail()] == null) {
|
if (exercisePlanRepository.exercisePlanDetails[exercisePlanRepository.getActualPlanDetail()] == null) {
|
||||||
exercisePlanRepository.getActualPlanDetail().change = ExercisePlanDetailChange.add;
|
exercisePlanRepository.getActualPlanDetail()!.change = ExercisePlanDetailChange.add;
|
||||||
} else {
|
} else {
|
||||||
exercisePlanRepository.getActualPlanDetail().change = ExercisePlanDetailChange.update;
|
exercisePlanRepository.getActualPlanDetail()!.change = ExercisePlanDetailChange.update;
|
||||||
}
|
}
|
||||||
exercisePlanRepository.addDetailToPlan();
|
exercisePlanRepository.addDetailToPlan();
|
||||||
planBloc.add(ExercisePlanAddExercise(exercisePlanDetail: exercisePlanRepository.getActualPlanDetail()));
|
planBloc.add(ExercisePlanAddExercise(exercisePlanDetail: exercisePlanRepository.getActualPlanDetail()!));
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
} else if (event is ExercisePlanCustomAddRemove) {
|
} else if (event is ExercisePlanCustomAddRemove) {
|
||||||
yield ExercisePlanCustomAddLoading();
|
yield ExercisePlanCustomAddLoading();
|
||||||
exercisePlanRepository.getActualPlanDetail().change = ExercisePlanDetailChange.delete;
|
exercisePlanRepository.getActualPlanDetail()!.change = ExercisePlanDetailChange.delete;
|
||||||
planBloc.add(ExercisePlanRemoveExercise(exercisePlanDetail: exercisePlanRepository.getActualPlanDetail()));
|
planBloc.add(ExercisePlanRemoveExercise(exercisePlanDetail: exercisePlanRepository.getActualPlanDetail()!));
|
||||||
|
|
||||||
yield ExercisePlanCustomAddReady();
|
yield ExercisePlanCustomAddReady();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ class ExercisePlanCustomAddLoad extends ExercisePlanCustomAddEvent {
|
|||||||
|
|
||||||
class ExercisePlanCustomAddChangeSerie extends ExercisePlanCustomAddEvent {
|
class ExercisePlanCustomAddChangeSerie extends ExercisePlanCustomAddEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExercisePlanCustomAddChangeSerie({this.quantity});
|
const ExercisePlanCustomAddChangeSerie({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -22,7 +22,7 @@ class ExercisePlanCustomAddChangeSerie extends ExercisePlanCustomAddEvent {
|
|||||||
|
|
||||||
class ExercisePlanCustomAddChangeQuantity extends ExercisePlanCustomAddEvent {
|
class ExercisePlanCustomAddChangeQuantity extends ExercisePlanCustomAddEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExercisePlanCustomAddChangeQuantity({this.quantity});
|
const ExercisePlanCustomAddChangeQuantity({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -30,7 +30,7 @@ class ExercisePlanCustomAddChangeQuantity extends ExercisePlanCustomAddEvent {
|
|||||||
|
|
||||||
class ExercisePlanCustomAddChangeQuantityUnit extends ExercisePlanCustomAddEvent {
|
class ExercisePlanCustomAddChangeQuantityUnit extends ExercisePlanCustomAddEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const ExercisePlanCustomAddChangeQuantityUnit({this.quantity});
|
const ExercisePlanCustomAddChangeQuantityUnit({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -42,4 +42,4 @@ class ExercisePlanCustomAddSubmit extends ExercisePlanCustomAddEvent {
|
|||||||
|
|
||||||
class ExercisePlanCustomAddRemove extends ExercisePlanCustomAddEvent {
|
class ExercisePlanCustomAddRemove extends ExercisePlanCustomAddEvent {
|
||||||
const ExercisePlanCustomAddRemove();
|
const ExercisePlanCustomAddRemove();
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,8 @@ class ExercisePlanCustomAddReady extends ExercisePlanCustomAddState {
|
|||||||
|
|
||||||
class ExercisePlanCustomAddError extends ExercisePlanCustomAddState {
|
class ExercisePlanCustomAddError extends ExercisePlanCustomAddState {
|
||||||
final String message;
|
final String message;
|
||||||
const ExercisePlanCustomAddError({this.message});
|
const ExercisePlanCustomAddError({required this.message});
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
final bool isRegistration;
|
final bool isRegistration;
|
||||||
bool dataPolicyAllowed = false;
|
bool dataPolicyAllowed = false;
|
||||||
bool obscure = true;
|
bool obscure = true;
|
||||||
LoginBloc({this.accountBloc, this.userRepository, this.context, this.isRegistration}) : super(LoginInitial());
|
|
||||||
|
LoginBloc({required this.accountBloc, required this.userRepository, required this.context, required this.isRegistration})
|
||||||
|
: super(LoginInitial());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<LoginState> mapEventToState(
|
Stream<LoginState> mapEventToState(
|
||||||
@ -43,7 +45,7 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
} else if (event is LoginSubmit) {
|
} else if (event is LoginSubmit) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
await userRepository.getUser();
|
await userRepository.getUser();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
Track().track(TrackingEvent.login, eventValue: "email");
|
Track().track(TrackingEvent.login, eventValue: "email");
|
||||||
Cache().setLoginType(LoginType.email);
|
Cache().setLoginType(LoginType.email);
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
@ -51,31 +53,30 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
Cache().setLoginType(LoginType.fb);
|
Cache().setLoginType(LoginType.fb);
|
||||||
await userRepository.getUserByFB();
|
await userRepository.getUserByFB();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
Track().track(TrackingEvent.login, eventValue: "FB");
|
Track().track(TrackingEvent.login, eventValue: "FB");
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is LoginGoogle) {
|
} else if (event is LoginGoogle) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
Cache().setLoginType(LoginType.google);
|
Cache().setLoginType(LoginType.google);
|
||||||
await userRepository.getUserByGoogle();
|
await userRepository.getUserByGoogle();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
Track().track(TrackingEvent.login, eventValue: "Google");
|
Track().track(TrackingEvent.login, eventValue: "Google");
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is LoginApple) {
|
} else if (event is LoginApple) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
Cache().setLoginType(LoginType.apple);
|
Cache().setLoginType(LoginType.apple);
|
||||||
await userRepository.getUserByApple();
|
await userRepository.getUserByApple();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
Track().track(TrackingEvent.login, eventValue: "Apple");
|
Track().track(TrackingEvent.login, eventValue: "Apple");
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationSubmit) {
|
} else if (event is RegistrationSubmit) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
if (!this.dataPolicyAllowed) {
|
||||||
yield LoginError();
|
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
}
|
||||||
await userRepository.addUser();
|
await userRepository.addUser();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
await saveCustomer();
|
await saveCustomer();
|
||||||
Track().track(TrackingEvent.registration, eventValue: "email");
|
Track().track(TrackingEvent.registration, eventValue: "email");
|
||||||
Cache().setLoginType(LoginType.email);
|
Cache().setLoginType(LoginType.email);
|
||||||
@ -83,36 +84,33 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
} else if (event is RegistrationFB) {
|
} else if (event is RegistrationFB) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
if (!this.dataPolicyAllowed) {
|
||||||
yield LoginError();
|
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
}
|
||||||
Cache().setLoginType(LoginType.fb);
|
Cache().setLoginType(LoginType.fb);
|
||||||
await userRepository.addUserFB();
|
await userRepository.addUserFB();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
await saveCustomer();
|
await saveCustomer();
|
||||||
Track().track(TrackingEvent.registration, eventValue: "FB");
|
Track().track(TrackingEvent.registration, eventValue: "FB");
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationGoogle) {
|
} else if (event is RegistrationGoogle) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
if (!this.dataPolicyAllowed) {
|
||||||
yield LoginError();
|
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
}
|
||||||
Cache().setLoginType(LoginType.google);
|
Cache().setLoginType(LoginType.google);
|
||||||
await userRepository.addUserGoogle();
|
await userRepository.addUserGoogle();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
await saveCustomer();
|
await saveCustomer();
|
||||||
Track().track(TrackingEvent.registration, eventValue: "Google");
|
Track().track(TrackingEvent.registration, eventValue: "Google");
|
||||||
yield LoginSuccess();
|
yield LoginSuccess();
|
||||||
} else if (event is RegistrationApple) {
|
} else if (event is RegistrationApple) {
|
||||||
yield LoginLoading();
|
yield LoginLoading();
|
||||||
if (!this.dataPolicyAllowed) {
|
if (!this.dataPolicyAllowed) {
|
||||||
yield LoginError();
|
|
||||||
throw Exception("Please accept our data policy");
|
throw Exception("Please accept our data policy");
|
||||||
}
|
}
|
||||||
Cache().setLoginType(LoginType.apple);
|
Cache().setLoginType(LoginType.apple);
|
||||||
await userRepository.addUserApple();
|
await userRepository.addUserApple();
|
||||||
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn));
|
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
|
||||||
await saveCustomer();
|
await saveCustomer();
|
||||||
Track().track(TrackingEvent.registration, eventValue: "Apple");
|
Track().track(TrackingEvent.registration, eventValue: "Apple");
|
||||||
|
|
||||||
@ -132,21 +130,18 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveCustomer() async {
|
Future<void> saveCustomer() async {
|
||||||
customerRepository.customer = Cache().userLoggedIn;
|
customerRepository.customer = Cache().userLoggedIn!;
|
||||||
customerRepository.customer.dataPolicyAllowed = 1;
|
customerRepository.customer.dataPolicyAllowed = 1;
|
||||||
await customerRepository.saveCustomer();
|
await customerRepository.saveCustomer();
|
||||||
}
|
}
|
||||||
|
|
||||||
String emailValidation(String email) {
|
String? emailValidation(String email) {
|
||||||
String message = Common.emailValidation(email);
|
String? message = Common.emailValidation(email);
|
||||||
if (message != null) {
|
|
||||||
message = t(message);
|
|
||||||
}
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
String passwordValidation(String value) {
|
String? passwordValidation(String value) {
|
||||||
String message = Common.passwordValidation(value);
|
String? message = Common.passwordValidation(value);
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
message = t(message);
|
message = t(message);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ abstract class LoginEvent extends Equatable {
|
|||||||
|
|
||||||
class LoginEmailChange extends LoginEvent {
|
class LoginEmailChange extends LoginEvent {
|
||||||
final String email;
|
final String email;
|
||||||
const LoginEmailChange({this.email});
|
const LoginEmailChange({required this.email});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [email];
|
List<Object> get props => [email];
|
||||||
@ -17,7 +17,7 @@ class LoginEmailChange extends LoginEvent {
|
|||||||
|
|
||||||
class LoginPasswordChange extends LoginEvent {
|
class LoginPasswordChange extends LoginEvent {
|
||||||
final String password;
|
final String password;
|
||||||
const LoginPasswordChange({this.password});
|
const LoginPasswordChange({required this.password});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [password];
|
List<Object> get props => [password];
|
||||||
@ -45,7 +45,7 @@ class LoginApple extends LoginEvent {
|
|||||||
|
|
||||||
class DataProtectionClicked extends LoginEvent {
|
class DataProtectionClicked extends LoginEvent {
|
||||||
final bool marked;
|
final bool marked;
|
||||||
const DataProtectionClicked({this.marked});
|
const DataProtectionClicked({required this.marked});
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegistrationSubmit extends LoginEvent {
|
class RegistrationSubmit extends LoginEvent {
|
||||||
|
@ -25,7 +25,7 @@ class LoginSuccess extends LoginState {
|
|||||||
|
|
||||||
class LoginError extends LoginState {
|
class LoginError extends LoginState {
|
||||||
final String message;
|
final String message;
|
||||||
const LoginError({this.message});
|
const LoginError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -23,8 +23,8 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
ExerciseDeviceRepository exerciseDeviceRepository = ExerciseDeviceRepository();
|
ExerciseDeviceRepository exerciseDeviceRepository = ExerciseDeviceRepository();
|
||||||
int parent = 0;
|
int parent = 0;
|
||||||
WorkoutMenuTree workoutItem;
|
WorkoutMenuTree? workoutItem;
|
||||||
final List<int> listFilterDevice = List();
|
final List<int> listFilterDevice = [];
|
||||||
|
|
||||||
String infoTitle = "";
|
String infoTitle = "";
|
||||||
String infoText = "";
|
String infoText = "";
|
||||||
@ -32,13 +32,13 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
String infoText3 = "";
|
String infoText3 = "";
|
||||||
String infoLink = "";
|
String infoLink = "";
|
||||||
int missingParent = 0;
|
int missingParent = 0;
|
||||||
String missingTreeName = "";
|
String? missingTreeName = "";
|
||||||
|
|
||||||
BuildContext context;
|
late BuildContext context;
|
||||||
|
|
||||||
ExerciseAbility ability;
|
ExerciseAbility? ability;
|
||||||
|
|
||||||
MenuBloc({this.menuTreeRepository}) : super(MenuInitial()) {
|
MenuBloc({required this.menuTreeRepository}) : super(MenuInitial()) {
|
||||||
parent = 0;
|
parent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
exerciseRepository.getBaseExerciseFinishedPercent();
|
exerciseRepository.getBaseExerciseFinishedPercent();
|
||||||
percent = Cache().getPercentExercises();
|
percent = Cache().getPercentExercises();
|
||||||
}
|
}
|
||||||
if (context == null) return;
|
|
||||||
percent = percent * 100;
|
percent = percent * 100;
|
||||||
//log("Percent " + percent.toString());
|
//log("Percent " + percent.toString());
|
||||||
if (percent == -1 || percent == 0) {
|
if (percent == -1 || percent == 0) {
|
||||||
@ -78,7 +78,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
//log("Missing " + missingTreeName);
|
//log("Missing " + missingTreeName);
|
||||||
if (missingTreeName != null) {
|
if (missingTreeName != null) {
|
||||||
if (percent > 0) {
|
if (percent > 0) {
|
||||||
infoText = t("Please continue your tests with a") + " '" + missingTreeName + "' " + t("exercise!");
|
infoText = t("Please continue your tests with a") + " '" + missingTreeName! + "' " + t("exercise!");
|
||||||
infoLink = t("Bring me there");
|
infoLink = t("Bring me there");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,13 +97,13 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
yield MenuLoading();
|
yield MenuLoading();
|
||||||
//await menuTreeRepository.createTree();
|
//await menuTreeRepository.createTree();
|
||||||
//menuTreeRepository.getBranch(this.parent);
|
//menuTreeRepository.getBranch(this.parent);
|
||||||
setMenuInfo();
|
//setMenuInfo();
|
||||||
exerciseDeviceRepository.setDevices(Cache().getDevices());
|
exerciseDeviceRepository.setDevices(Cache().getDevices()!);
|
||||||
yield MenuReady();
|
yield MenuReady();
|
||||||
} else if (event is MenuRecreateTree) {
|
} else if (event is MenuRecreateTree) {
|
||||||
yield MenuLoading();
|
yield MenuLoading();
|
||||||
// ie. at language changes
|
// ie. at language changes
|
||||||
await menuTreeRepository.createTree();
|
menuTreeRepository.createTree();
|
||||||
yield MenuReady();
|
yield MenuReady();
|
||||||
} else if (event is MenuTreeDown) {
|
} else if (event is MenuTreeDown) {
|
||||||
yield MenuLoading();
|
yield MenuLoading();
|
||||||
@ -111,7 +111,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
workoutItem = event.item;
|
workoutItem = event.item;
|
||||||
|
|
||||||
if (workoutItem != null) {
|
if (workoutItem != null) {
|
||||||
setAbility(workoutItem.nameEnglish);
|
setAbility(workoutItem!.nameEnglish);
|
||||||
}
|
}
|
||||||
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(event.parent);
|
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(event.parent);
|
||||||
|
|
||||||
@ -126,8 +126,8 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
|
|
||||||
LinkedHashMap<String, WorkoutMenuTree> branch;
|
LinkedHashMap<String, WorkoutMenuTree> branch;
|
||||||
if (workoutItem != null) {
|
if (workoutItem != null) {
|
||||||
setAbility(workoutItem.nameEnglish);
|
setAbility(workoutItem!.nameEnglish);
|
||||||
branch = menuTreeRepository.getBranch(workoutItem.parent);
|
branch = menuTreeRepository.getBranch(workoutItem!.parent);
|
||||||
await getImages(branch);
|
await getImages(branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,12 +138,11 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
workoutItem = menuTreeRepository.getParentItem(parent);
|
workoutItem = menuTreeRepository.getParentItem(parent);
|
||||||
|
|
||||||
if (workoutItem != null) {
|
if (workoutItem != null) {
|
||||||
setAbility(workoutItem.nameEnglish);
|
setAbility(workoutItem!.nameEnglish);
|
||||||
}
|
|
||||||
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(workoutItem.parent);
|
|
||||||
if (branch != null) {
|
|
||||||
await getImages(branch);
|
|
||||||
}
|
}
|
||||||
|
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(workoutItem!.parent);
|
||||||
|
await getImages(branch);
|
||||||
|
|
||||||
yield MenuReady();
|
yield MenuReady();
|
||||||
} else if (event is MenuClickExercise) {
|
} else if (event is MenuClickExercise) {
|
||||||
yield MenuLoading();
|
yield MenuLoading();
|
||||||
@ -193,15 +192,15 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
|
|
||||||
Future<void> putBranchImageToHash(LinkedHashMap<String, WorkoutMenuTree> branch) async {
|
Future<void> putBranchImageToHash(LinkedHashMap<String, WorkoutMenuTree> branch) async {
|
||||||
await Future.forEach(branch.keys, (key) async {
|
await Future.forEach(branch.keys, (key) async {
|
||||||
final WorkoutMenuTree value = branch[key];
|
final WorkoutMenuTree? value = branch[key];
|
||||||
if (!value.imageName.contains("asset")) {
|
if (value != null && !value.imageName.contains("asset")) {
|
||||||
await wt.ImageCache().putImageToList(value.id, value.imageName);
|
await wt.ImageCache().putImageToList(value.id, value.imageName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
String getImage(int id, String name) {
|
String? getImage(int id, String name) {
|
||||||
String imageString;
|
String? imageString;
|
||||||
if (name.contains("http")) {
|
if (name.contains("http")) {
|
||||||
imageString = wt.ImageCache().getImageString(id, name);
|
imageString = wt.ImageCache().getImageString(id, name);
|
||||||
}
|
}
|
||||||
@ -212,7 +211,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
return !listFilterDevice.contains(deviceId);
|
return !listFilterDevice.contains(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedHashMap<String, WorkoutMenuTree> getFilteredBranch(int parent) {
|
LinkedHashMap<String, WorkoutMenuTree> getFilteredBranch(int? parent) {
|
||||||
if (parent == null) return LinkedHashMap();
|
if (parent == null) return LinkedHashMap();
|
||||||
|
|
||||||
LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(parent);
|
LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(parent);
|
||||||
@ -224,8 +223,8 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
|
|||||||
branch.forEach((key, value) {
|
branch.forEach((key, value) {
|
||||||
final WorkoutMenuTree elem = value;
|
final WorkoutMenuTree elem = value;
|
||||||
if (elem.exerciseType != null) {
|
if (elem.exerciseType != null) {
|
||||||
for (int i = 0; i < elem.exerciseType.devices.length; i++) {
|
for (int i = 0; i < elem.exerciseType!.devices.length; i++) {
|
||||||
if (listFilterDevice.contains(elem.exerciseType.devices[i])) {
|
if (listFilterDevice.contains(elem.exerciseType!.devices[i])) {
|
||||||
filtered[elem.name] = elem;
|
filtered[elem.name] = elem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,26 +16,26 @@ class MenuCreate extends MenuEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MenuTreeDown extends MenuEvent {
|
class MenuTreeDown extends MenuEvent {
|
||||||
final WorkoutMenuTree item;
|
final WorkoutMenuTree? item;
|
||||||
final int parent;
|
final int parent;
|
||||||
const MenuTreeDown({this.parent, this.item});
|
MenuTreeDown({required this.parent, this.item});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [parent, item];
|
List<Object> get props => [parent];
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuTreeUp extends MenuEvent {
|
class MenuTreeUp extends MenuEvent {
|
||||||
final int parent;
|
final int parent;
|
||||||
final WorkoutMenuTree item;
|
final WorkoutMenuTree? item;
|
||||||
const MenuTreeUp({this.parent, this.item});
|
const MenuTreeUp({required this.parent, this.item});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [parent, item];
|
List<Object> get props => [parent];
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuTreeJump extends MenuEvent {
|
class MenuTreeJump extends MenuEvent {
|
||||||
final int parent;
|
final int parent;
|
||||||
const MenuTreeJump({this.parent});
|
const MenuTreeJump({required this.parent});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [parent];
|
List<Object> get props => [parent];
|
||||||
@ -43,7 +43,7 @@ class MenuTreeJump extends MenuEvent {
|
|||||||
|
|
||||||
class MenuClickExercise extends MenuEvent {
|
class MenuClickExercise extends MenuEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const MenuClickExercise({this.exerciseTypeId});
|
const MenuClickExercise({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
@ -55,5 +55,5 @@ class MenuRecreateTree extends MenuEvent {
|
|||||||
|
|
||||||
class MenuFilterExerciseType extends MenuEvent {
|
class MenuFilterExerciseType extends MenuEvent {
|
||||||
final int deviceId;
|
final int deviceId;
|
||||||
const MenuFilterExerciseType({this.deviceId});
|
const MenuFilterExerciseType({required this.deviceId});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
part of 'menu_bloc.dart';
|
part of 'menu_bloc.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
abstract class MenuState extends Equatable {
|
abstract class MenuState extends Equatable {
|
||||||
const MenuState();
|
const MenuState();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -12,22 +12,15 @@ class MenuInitial extends MenuState {
|
|||||||
const MenuInitial();
|
const MenuInitial();
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuLoading extends MenuState {
|
class MenuLoading extends MenuState {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class MenuReady extends MenuState {
|
class MenuReady extends MenuState {
|
||||||
final WorkoutMenuTree workoutTree;
|
const MenuReady();
|
||||||
|
|
||||||
const MenuReady({this.workoutTree});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [workoutTree];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuError extends MenuState {
|
class MenuError extends MenuState {
|
||||||
final String message;
|
final String message;
|
||||||
const MenuError({this.message});
|
const MenuError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
40
lib/bloc/password_reset/password_reset_bloc.dart
Normal file
40
lib/bloc/password_reset/password_reset_bloc.dart
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/repository/user_repository.dart';
|
||||||
|
import 'package:aitrainer_app/util/common.dart';
|
||||||
|
import 'package:bloc/bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
part 'password_reset_event.dart';
|
||||||
|
part 'password_reset_state.dart';
|
||||||
|
|
||||||
|
class PasswordResetBloc extends Bloc<PasswordResetEvent, PasswordResetState> {
|
||||||
|
final UserRepository userRepository;
|
||||||
|
PasswordResetBloc({required this.userRepository}) : super(PasswordResetInitial());
|
||||||
|
|
||||||
|
@override
|
||||||
|
Stream<PasswordResetState> mapEventToState(
|
||||||
|
PasswordResetEvent event,
|
||||||
|
) async* {
|
||||||
|
try {
|
||||||
|
if (event is PasswordResetEmailChange) {
|
||||||
|
yield PasswordResetLoading();
|
||||||
|
final String email = event.email;
|
||||||
|
userRepository.setEmail(email);
|
||||||
|
yield PasswordResetReady();
|
||||||
|
} else if (event is PasswordResetSubmit) {
|
||||||
|
yield PasswordResetLoading();
|
||||||
|
await userRepository.resetPassword();
|
||||||
|
yield PasswordResetReady();
|
||||||
|
}
|
||||||
|
} on Exception catch (e) {
|
||||||
|
yield PasswordResetError(message: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String? emailValidation(String email) {
|
||||||
|
String? message = Common.emailValidation(email);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
24
lib/bloc/password_reset/password_reset_event.dart
Normal file
24
lib/bloc/password_reset/password_reset_event.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
part of 'password_reset_bloc.dart';
|
||||||
|
|
||||||
|
abstract class PasswordResetEvent extends Equatable {
|
||||||
|
const PasswordResetEvent();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetEmailChange extends PasswordResetEvent {
|
||||||
|
final String email;
|
||||||
|
const PasswordResetEmailChange({required this.email});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [email];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetLoad extends PasswordResetEvent {
|
||||||
|
const PasswordResetLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetSubmit extends PasswordResetEvent {
|
||||||
|
const PasswordResetSubmit();
|
||||||
|
}
|
28
lib/bloc/password_reset/password_reset_state.dart
Normal file
28
lib/bloc/password_reset/password_reset_state.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
part of 'password_reset_bloc.dart';
|
||||||
|
|
||||||
|
abstract class PasswordResetState extends Equatable {
|
||||||
|
const PasswordResetState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetInitial extends PasswordResetState {
|
||||||
|
const PasswordResetInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetLoading extends PasswordResetState {
|
||||||
|
const PasswordResetLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetError extends PasswordResetState {
|
||||||
|
final String message;
|
||||||
|
const PasswordResetError({required this.message});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [message];
|
||||||
|
}
|
||||||
|
|
||||||
|
class PasswordResetReady extends PasswordResetState {
|
||||||
|
const PasswordResetReady();
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
import 'package:aitrainer_app/repository/user_repository.dart';
|
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
|
||||||
|
|
||||||
class ResetPasswordFormBloc extends FormBloc<String, String> with Common {
|
|
||||||
final UserRepository userRepository;
|
|
||||||
bool loading = false;
|
|
||||||
|
|
||||||
final emailField = TextFieldBloc(
|
|
||||||
validators: [
|
|
||||||
FieldBlocValidators.required,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
ResetPasswordFormBloc({this.userRepository}) {
|
|
||||||
addFieldBlocs(fieldBlocs: [emailField]);
|
|
||||||
|
|
||||||
emailField.onValueChanges(onData: (previous, current) async* {
|
|
||||||
userRepository.setEmail(current.value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void onSubmitting() async {
|
|
||||||
try {
|
|
||||||
emitLoading(progress: 30);
|
|
||||||
loading = true;
|
|
||||||
if (!validateEmail(userRepository)) {
|
|
||||||
emailField.addFieldError(EMAIL_ERROR, isPermanent: true);
|
|
||||||
|
|
||||||
emitFailure(failureResponse: EMAIL_ERROR);
|
|
||||||
} else {
|
|
||||||
// Emit either Loaded or Error
|
|
||||||
await userRepository.resetPassword();
|
|
||||||
emitSuccess(canSubmitAgain: false);
|
|
||||||
}
|
|
||||||
loading = false;
|
|
||||||
} on Exception catch (ex) {
|
|
||||||
emitFailure(failureResponse: ex.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> close() {
|
|
||||||
emailField.close();
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ import 'package:aitrainer_app/util/trans.dart';
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
|
||||||
//import 'package:health/health.dart';
|
//import 'package:health/health.dart';
|
||||||
|
|
||||||
part 'result_event.dart';
|
part 'result_event.dart';
|
||||||
@ -18,9 +18,9 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
final ExerciseResultRepository resultRepository;
|
final ExerciseResultRepository resultRepository;
|
||||||
final ExerciseRepository exerciseRepository;
|
final ExerciseRepository exerciseRepository;
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
//List<HealthDataPoint> _healthDataList = List();
|
//List<HealthDataPoint> _healthDataList = [];
|
||||||
DateTime startTime;
|
DateTime? startTime;
|
||||||
DateTime endTime;
|
DateTime? endTime;
|
||||||
/* final HealthFactory health = HealthFactory();
|
/* final HealthFactory health = HealthFactory();
|
||||||
final List<HealthDataType> types = [
|
final List<HealthDataType> types = [
|
||||||
HealthDataType.ACTIVE_ENERGY_BURNED,
|
HealthDataType.ACTIVE_ENERGY_BURNED,
|
||||||
@ -34,12 +34,12 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
HealthDataType.RESTING_HEART_RATE
|
HealthDataType.RESTING_HEART_RATE
|
||||||
]; */
|
]; */
|
||||||
|
|
||||||
ResultBloc({this.resultRepository, this.exerciseRepository, this.context}) : super(ResultInitial()) {
|
ResultBloc({required this.resultRepository, required this.exerciseRepository, required this.context}) : super(ResultInitial()) {
|
||||||
this.startTime = exerciseRepository.start;
|
this.startTime = exerciseRepository.start;
|
||||||
this.endTime = exerciseRepository.end;
|
this.endTime = exerciseRepository.end;
|
||||||
if (this.startTime == null) {
|
if (this.startTime == null) {
|
||||||
this.startTime = exerciseRepository.exercise.dateAdd;
|
this.startTime = exerciseRepository.exercise!.dateAdd!;
|
||||||
exerciseRepository.start = exerciseRepository.exercise.dateAdd;
|
exerciseRepository.start = exerciseRepository.exercise!.dateAdd!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
resultRepository.getResults().forEach((element) {
|
resultRepository.getResults().forEach((element) {
|
||||||
element.dateFrom = startTime;
|
element.dateFrom = startTime;
|
||||||
element.dateTo = endTime;
|
element.dateTo = endTime;
|
||||||
element.exerciseId = exerciseRepository.actualExerciseList[0].exerciseId;
|
element.exerciseId = exerciseRepository.actualExerciseList![0].exerciseId;
|
||||||
switch (element.item) {
|
switch (element.item) {
|
||||||
case ResultItem.bpm_avg:
|
case ResultItem.bpm_avg:
|
||||||
//element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE);
|
//element.data = _gethHealthDataPointValueAvg(HealthDataType.HEART_RATE);
|
||||||
@ -80,11 +80,10 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
//element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED);
|
//element.data = _gethHealthDataPointValueSum(HealthDataType.ACTIVE_ENERGY_BURNED);
|
||||||
break;
|
break;
|
||||||
case ResultItem.development_percent_bodypart:
|
case ResultItem.development_percent_bodypart:
|
||||||
// TODO: Handle this case.
|
|
||||||
break;
|
break;
|
||||||
case ResultItem.distance:
|
case ResultItem.distance:
|
||||||
if (exerciseRepository.exerciseType.unit == "meter") {
|
if (exerciseRepository.exerciseType!.unit == "meter") {
|
||||||
element.data = exerciseRepository.exercise.quantity;
|
element.data = exerciseRepository.exercise!.quantity!;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ResultItem.fatburn_percent:
|
case ResultItem.fatburn_percent:
|
||||||
@ -109,13 +108,12 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
} */
|
} */
|
||||||
break;
|
break;
|
||||||
case ResultItem.speed_max:
|
case ResultItem.speed_max:
|
||||||
// TODO: Handle this case.
|
|
||||||
break;
|
break;
|
||||||
case ResultItem.reps_volume:
|
case ResultItem.reps_volume:
|
||||||
if (exerciseRepository.exerciseType.unit == "repeat") {
|
if (exerciseRepository.exerciseType!.unit == "repeat") {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
exerciseRepository.actualExerciseList.forEach((actual) {
|
exerciseRepository.actualExerciseList!.forEach((actual) {
|
||||||
value += actual.quantity;
|
value += actual.quantity!;
|
||||||
});
|
});
|
||||||
element.data = value;
|
element.data = value;
|
||||||
}
|
}
|
||||||
@ -128,10 +126,10 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
element.data = _printDuration(duration);
|
element.data = _printDuration(duration);
|
||||||
break; */
|
break; */
|
||||||
case ResultItem.weight_volume:
|
case ResultItem.weight_volume:
|
||||||
if (exerciseRepository.exerciseType.unitQuantityUnit == "kilogram") {
|
if (exerciseRepository.exerciseType!.unitQuantityUnit == "kilogram") {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
exerciseRepository.actualExerciseList.forEach((actual) {
|
exerciseRepository.actualExerciseList!.forEach((actual) {
|
||||||
value += actual.quantity * actual.unitQuantity;
|
value += actual.quantity! * actual.unitQuantity!;
|
||||||
});
|
});
|
||||||
element.data = value;
|
element.data = value;
|
||||||
}
|
}
|
||||||
@ -233,12 +231,12 @@ class ResultBloc extends Bloc<ResultEvent, ResultState> with Logging, Trans {
|
|||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
|
|
||||||
double calculate1RM({double percent}) {
|
double calculate1RM({double percent = 0.75}) {
|
||||||
if (exerciseRepository.exercise == null) {
|
if (exerciseRepository.exercise == null) {
|
||||||
exerciseRepository.getLastExercise();
|
exerciseRepository.getLastExercise();
|
||||||
}
|
}
|
||||||
double weight = exerciseRepository.exercise.unitQuantity;
|
double weight = exerciseRepository.exercise!.unitQuantity!;
|
||||||
double repeat = exerciseRepository.exercise.quantity;
|
double repeat = exerciseRepository.exercise!.quantity!;
|
||||||
if (weight == 0 || repeat == 0) {
|
if (weight == 0 || repeat == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ class ResultReady extends ResultState {
|
|||||||
|
|
||||||
class ResultError extends ResultState {
|
class ResultError extends ResultState {
|
||||||
final String error;
|
final String error;
|
||||||
const ResultError({this.error});
|
const ResultError({required this.error});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [this.error];
|
List<Object> get props => [this.error];
|
||||||
|
@ -8,21 +8,19 @@ import 'package:aitrainer_app/model/product_test.dart';
|
|||||||
import 'package:aitrainer_app/model/purchase.dart';
|
import 'package:aitrainer_app/model/purchase.dart';
|
||||||
import 'package:aitrainer_app/service/logging.dart';
|
import 'package:aitrainer_app/service/logging.dart';
|
||||||
import 'package:aitrainer_app/service/purchase_service.dart';
|
import 'package:aitrainer_app/service/purchase_service.dart';
|
||||||
import 'package:aitrainer_app/util/common.dart';
|
|
||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/purchases.dart';
|
import 'package:aitrainer_app/util/purchases.dart';
|
||||||
import 'package:aitrainer_app/util/track.dart';
|
import 'package:aitrainer_app/util/track.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
|
||||||
import 'package:purchases_flutter/offering_wrapper.dart';
|
import 'package:purchases_flutter/offering_wrapper.dart';
|
||||||
|
|
||||||
part 'sales_event.dart';
|
part 'sales_event.dart';
|
||||||
part 'sales_state.dart';
|
part 'sales_state.dart';
|
||||||
|
|
||||||
class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
||||||
List<ProductTest> tests = List();
|
List<ProductTest>? tests = [];
|
||||||
List<Product> product2Display = List();
|
List<Product> product2Display = [];
|
||||||
int productSet = -1;
|
int productSet = -1;
|
||||||
SalesBloc() : super(SalesInitial());
|
SalesBloc() : super(SalesInitial());
|
||||||
|
|
||||||
@ -35,7 +33,6 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
yield SalesLoading();
|
yield SalesLoading();
|
||||||
log("Load Sales");
|
log("Load Sales");
|
||||||
Track().track(TrackingEvent.sales_page);
|
Track().track(TrackingEvent.sales_page);
|
||||||
//await PlatformPurchaseApi().initPurchasePlatform();
|
|
||||||
await RevenueCatPurchases().getOfferings();
|
await RevenueCatPurchases().getOfferings();
|
||||||
this.getProductSet();
|
this.getProductSet();
|
||||||
yield SalesReady();
|
yield SalesReady();
|
||||||
@ -47,27 +44,30 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
final int productId = event.productId;
|
final int productId = event.productId;
|
||||||
log("Requesting purchase for: " + productId.toString());
|
log("Requesting purchase for: " + productId.toString());
|
||||||
Track().track(TrackingEvent.purchase_request);
|
Track().track(TrackingEvent.purchase_request);
|
||||||
final Product selectedProduct = this.getSelectedProduct(productId);
|
final Product? selectedProduct = this.getSelectedProduct(productId);
|
||||||
log("SelectedProduct for purchase " + selectedProduct.toString());
|
log("SelectedProduct for purchase $selectedProduct");
|
||||||
await RevenueCatPurchases().makePurchase(selectedProduct);
|
if (selectedProduct != null) {
|
||||||
if (Cache().hasPurchased) {
|
await RevenueCatPurchases().makePurchase(selectedProduct);
|
||||||
Purchase purchase = Purchase(customerId: Cache().userLoggedIn.customerId, productId: productId);
|
if (Cache().hasPurchased) {
|
||||||
purchase.dateAdd = DateTime.now();
|
Purchase purchase = Purchase(customerId: Cache().userLoggedIn!.customerId!, productId: productId);
|
||||||
purchase.purchaseSum = 0;
|
purchase.dateAdd = DateTime.now();
|
||||||
purchase.currency = "EUR";
|
purchase.purchaseSum = 0;
|
||||||
await PurchaseApi().savePurchase(purchase);
|
purchase.currency = "EUR";
|
||||||
Track().track(TrackingEvent.purchase_successful, eventValue: selectedProduct.localizedPrice.toString());
|
await PurchaseApi().savePurchase(purchase);
|
||||||
Common.sendMessage("Purchase: " + purchase.toJson().toString());
|
Track().track(TrackingEvent.purchase_successful, eventValue: selectedProduct.localizedPrice.toString());
|
||||||
|
}
|
||||||
|
yield SalesSuccessful();
|
||||||
|
} else {
|
||||||
|
yield SalesError(message: "No selected product");
|
||||||
}
|
}
|
||||||
yield SalesSuccessful();
|
|
||||||
}
|
}
|
||||||
} on Exception catch (ex) {
|
} on Exception catch (ex) {
|
||||||
yield SalesError(message: ex.toString());
|
yield SalesError(message: ex.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Product getSelectedProduct(int productId) {
|
Product? getSelectedProduct(int productId) {
|
||||||
Product prod;
|
Product? prod;
|
||||||
for (var product in this.product2Display) {
|
for (var product in this.product2Display) {
|
||||||
if (product.productId == productId) {
|
if (product.productId == productId) {
|
||||||
prod = product;
|
prod = product;
|
||||||
@ -78,7 +78,7 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
|
|
||||||
String getLocalizedPrice(String productId) {
|
String getLocalizedPrice(String productId) {
|
||||||
String price = "";
|
String price = "";
|
||||||
Offering offering = RevenueCatPurchases().offering;
|
Offering? offering = RevenueCatPurchases().offering;
|
||||||
if (offering != null) {
|
if (offering != null) {
|
||||||
for (var package in offering.availablePackages) {
|
for (var package in offering.availablePackages) {
|
||||||
log("PlatformProduct " + package.toString());
|
log("PlatformProduct " + package.toString());
|
||||||
@ -100,15 +100,19 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
void getProductSet() {
|
void getProductSet() {
|
||||||
int productId = 0;
|
int productId = 0;
|
||||||
this.tests = Cache().productTests;
|
this.tests = Cache().productTests;
|
||||||
|
List<Product>? products = Cache().products;
|
||||||
|
if (products == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tests.isEmpty) {
|
if (tests != null && tests!.isEmpty) {
|
||||||
var rand = math.Random.secure();
|
var rand = math.Random.secure();
|
||||||
productSet = rand.nextInt(5) + 1;
|
productSet = rand.nextInt(5) + 1;
|
||||||
} else {
|
} else {
|
||||||
trace("Previous ProductTest: " + tests[0].toJson().toString());
|
trace("Previous ProductTest: " + tests![0].toJson().toString());
|
||||||
productId = tests[0].productId;
|
productId = tests![0].productId;
|
||||||
for (var elem in Cache().products) {
|
for (var elem in products) {
|
||||||
final Product product = elem as Product;
|
final Product product = elem;
|
||||||
if (product.productId == productId) {
|
if (product.productId == productId) {
|
||||||
productSet = product.productSet;
|
productSet = product.productSet;
|
||||||
break;
|
break;
|
||||||
@ -120,12 +124,12 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
|
|
||||||
productSet = 2;
|
productSet = 2;
|
||||||
log("ProductSet: " + productSet.toString());
|
log("ProductSet: " + productSet.toString());
|
||||||
for (var elem in Cache().products) {
|
for (var elem in products) {
|
||||||
Product product = elem as Product;
|
Product product = elem;
|
||||||
|
|
||||||
if (product.productSet == productSet) {
|
if (product.productSet == productSet) {
|
||||||
productId = product.productId;
|
productId = product.productId;
|
||||||
final String platformProductId = Platform.isAndroid ? product.productIdAndroid : product.productIdIos;
|
final String platformProductId = Platform.isAndroid ? product.productIdAndroid! : product.productIdIos!;
|
||||||
product.localizedPrice = getLocalizedPrice(platformProductId);
|
product.localizedPrice = getLocalizedPrice(platformProductId);
|
||||||
product2Display.add(product);
|
product2Display.add(product);
|
||||||
}
|
}
|
||||||
@ -136,7 +140,7 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
|
|||||||
});
|
});
|
||||||
|
|
||||||
productTest.productId = productId;
|
productTest.productId = productId;
|
||||||
productTest.customerId = Cache().userLoggedIn.customerId;
|
productTest.customerId = Cache().userLoggedIn!.customerId!;
|
||||||
productTest.dateView = DateTime.now();
|
productTest.dateView = DateTime.now();
|
||||||
//ProductTestApi().saveProductTest(productTest);
|
//ProductTestApi().saveProductTest(productTest);
|
||||||
//Cache().productTests.add(productTest);
|
//Cache().productTests.add(productTest);
|
||||||
|
@ -13,5 +13,5 @@ class SalesLoad extends SalesEvent {
|
|||||||
|
|
||||||
class SalesPurchase extends SalesEvent {
|
class SalesPurchase extends SalesEvent {
|
||||||
final int productId;
|
final int productId;
|
||||||
const SalesPurchase({this.productId});
|
const SalesPurchase({required this.productId});
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class SalesSuccessful extends SalesState {
|
|||||||
|
|
||||||
class SalesError extends SalesState {
|
class SalesError extends SalesState {
|
||||||
final String message;
|
final String message;
|
||||||
const SalesError({this.message});
|
const SalesError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -13,7 +13,7 @@ part 'session_state.dart';
|
|||||||
class SessionBloc extends Bloc<SessionEvent, SessionState> with Logging {
|
class SessionBloc extends Bloc<SessionEvent, SessionState> with Logging {
|
||||||
final Session session;
|
final Session session;
|
||||||
|
|
||||||
SessionBloc({this.session}) : super(SessionInitial());
|
SessionBloc({required this.session}) : super(SessionInitial());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<SessionState> mapEventToState(
|
Stream<SessionState> mapEventToState(
|
||||||
|
@ -9,7 +9,7 @@ abstract class SessionEvent extends Equatable {
|
|||||||
|
|
||||||
class SessionStart extends SessionEvent {
|
class SessionStart extends SessionEvent {
|
||||||
final SettingsBloc settingsBloc;
|
final SettingsBloc settingsBloc;
|
||||||
const SessionStart({this.settingsBloc});
|
const SessionStart({required this.settingsBloc});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [settingsBloc];
|
List<Object> get props => [settingsBloc];
|
||||||
|
@ -21,7 +21,7 @@ class SessionReady extends SessionState {
|
|||||||
|
|
||||||
class SessionFailure extends SessionState {
|
class SessionFailure extends SessionState {
|
||||||
final String message;
|
final String message;
|
||||||
const SessionFailure({this.message});
|
const SessionFailure({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -16,9 +16,9 @@ part 'settings_event.dart';
|
|||||||
part 'settings_state.dart';
|
part 'settings_state.dart';
|
||||||
|
|
||||||
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
||||||
String language;
|
String? language;
|
||||||
Locale _locale;
|
Locale? _locale;
|
||||||
BuildContext context;
|
BuildContext? context;
|
||||||
|
|
||||||
SettingsBloc({this.context}) : super(SettingsInitial());
|
SettingsBloc({this.context}) : super(SettingsInitial());
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
|||||||
_locale = locale;
|
_locale = locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
Locale getLocale() {
|
Locale? getLocale() {
|
||||||
return _locale;
|
return _locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,11 +37,11 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
|||||||
if (event is SettingsChangeLanguage) {
|
if (event is SettingsChangeLanguage) {
|
||||||
yield SettingsLoading();
|
yield SettingsLoading();
|
||||||
await _changeLang(event.language);
|
await _changeLang(event.language);
|
||||||
yield SettingsReady(_locale);
|
yield SettingsReady();
|
||||||
} else if (event is SettingsGetLanguage) {
|
} else if (event is SettingsGetLanguage) {
|
||||||
await AppLanguage().fetchLocale();
|
await AppLanguage().fetchLocale();
|
||||||
_locale = AppLanguage().appLocal;
|
_locale = AppLanguage().appLocal;
|
||||||
yield SettingsReady(_locale);
|
yield SettingsReady();
|
||||||
} else if (event is SettingsSetServer) {
|
} else if (event is SettingsSetServer) {
|
||||||
//yield SettingsLoading();
|
//yield SettingsLoading();
|
||||||
final bool live = event.live;
|
final bool live = event.live;
|
||||||
@ -60,7 +60,7 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
|||||||
await _accessHealthData();
|
await _accessHealthData();
|
||||||
}
|
}
|
||||||
Cache().initBadges();
|
Cache().initBadges();
|
||||||
yield SettingsReady(_locale);
|
yield SettingsReady();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,17 +97,17 @@ class SettingsBloc extends Bloc<SettingsEvent, SettingsState> with Logging {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.language = lang;
|
this.language = lang;
|
||||||
AppLanguage().changeLanguage(_locale);
|
AppLanguage().changeLanguage(_locale!);
|
||||||
await loadLang();
|
await loadLang();
|
||||||
await Cache().initBadges();
|
Cache().initBadges();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadLang() async {
|
Future<void> loadLang() async {
|
||||||
if (_locale != null) {
|
if (_locale != null) {
|
||||||
log(" -- Loading lang $_locale");
|
log(" -- Loading lang $_locale");
|
||||||
if (context != null) {
|
if (context != null) {
|
||||||
AppLocalizations.of(context).setLocale(_locale);
|
AppLocalizations.of(context!)!.setLocale(_locale!);
|
||||||
await AppLocalizations.of(context).load();
|
await AppLocalizations.of(context!)!.load();
|
||||||
} else {
|
} else {
|
||||||
log("no context, does not load");
|
log("no context, does not load");
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ abstract class SettingsEvent extends Equatable {
|
|||||||
|
|
||||||
class SettingsChangeLanguage extends SettingsEvent {
|
class SettingsChangeLanguage extends SettingsEvent {
|
||||||
final String language;
|
final String language;
|
||||||
const SettingsChangeLanguage({this.language});
|
const SettingsChangeLanguage({required this.language});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsGetLanguage extends SettingsEvent {
|
class SettingsGetLanguage extends SettingsEvent {
|
||||||
@ -18,7 +18,7 @@ class SettingsGetLanguage extends SettingsEvent {
|
|||||||
|
|
||||||
class SettingsSetServer extends SettingsEvent {
|
class SettingsSetServer extends SettingsEvent {
|
||||||
final bool live;
|
final bool live;
|
||||||
const SettingsSetServer({this.live});
|
const SettingsSetServer({required this.live});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [this.live];
|
List<Object> get props => [this.live];
|
||||||
@ -26,7 +26,7 @@ class SettingsSetServer extends SettingsEvent {
|
|||||||
|
|
||||||
class SettingsSetHardware extends SettingsEvent {
|
class SettingsSetHardware extends SettingsEvent {
|
||||||
final bool hasHardware;
|
final bool hasHardware;
|
||||||
const SettingsSetHardware({this.hasHardware});
|
const SettingsSetHardware({required this.hasHardware});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [this.hasHardware];
|
List<Object> get props => [this.hasHardware];
|
||||||
|
@ -10,31 +10,15 @@ abstract class SettingsState extends Equatable {
|
|||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class SettingsInitial extends SettingsState {
|
class SettingsInitial extends SettingsState {
|
||||||
Locale locale;
|
|
||||||
SettingsInitial();
|
SettingsInitial();
|
||||||
|
|
||||||
setLocale(locale) {
|
|
||||||
this.locale = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [locale];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsLoading extends SettingsState {
|
class SettingsLoading extends SettingsState {
|
||||||
final Locale locale;
|
const SettingsLoading();
|
||||||
const SettingsLoading({this.locale});
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [locale];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsReady extends SettingsState {
|
class SettingsReady extends SettingsState {
|
||||||
final Locale locale;
|
const SettingsReady();
|
||||||
const SettingsReady(this.locale);
|
|
||||||
|
|
||||||
@override
|
|
||||||
List<Object> get props => [locale];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SettingsError extends SettingsState {
|
class SettingsError extends SettingsState {
|
||||||
@ -43,4 +27,4 @@ class SettingsError extends SettingsState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
}
|
}
|
||||||
|
@ -17,30 +17,31 @@ class TestSetControlBloc extends Bloc<TestSetControlEvent, TestSetControlState>
|
|||||||
final TestSetExecuteBloc executeBloc;
|
final TestSetExecuteBloc executeBloc;
|
||||||
final ExerciseType exerciseType;
|
final ExerciseType exerciseType;
|
||||||
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
final ExerciseRepository exerciseRepository = ExerciseRepository();
|
||||||
TestSetControlBloc({this.exercisePlanDetail, this.executeBloc, this.exerciseType}) : super(TestSetControlInitial()) {
|
|
||||||
|
late double initQuantity;
|
||||||
|
late double initUnitQuantity;
|
||||||
|
late double quantity;
|
||||||
|
late double unitQuantity;
|
||||||
|
late double oneRepMax;
|
||||||
|
late int step;
|
||||||
|
|
||||||
|
TestSetControlBloc({required this.exercisePlanDetail, required this.executeBloc, required this.exerciseType})
|
||||||
|
: super(TestSetControlInitial()) {
|
||||||
initBloc();
|
initBloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initBloc() {
|
void initBloc() {
|
||||||
if (exercisePlanDetail.exerciseType.unitQuantity != null) {
|
oneRepMax = executeBloc.calculate1RM(exercisePlanDetail.exercises!.last.unitQuantity, exercisePlanDetail.exercises!.last.quantity);
|
||||||
oneRepMax = executeBloc.calculate1RM(exercisePlanDetail.exercises.last.unitQuantity, exercisePlanDetail.exercises.last.quantity);
|
initQuantity = 12;
|
||||||
initQuantity = 12;
|
quantity = initQuantity;
|
||||||
quantity = initQuantity;
|
initUnitQuantity = oneRepMax * 0.75;
|
||||||
initUnitQuantity = oneRepMax * 0.75;
|
unitQuantity = initUnitQuantity;
|
||||||
unitQuantity = initUnitQuantity;
|
|
||||||
}
|
step = exercisePlanDetail.exercises!.length;
|
||||||
step = exercisePlanDetail.exercises.length;
|
|
||||||
exerciseRepository.customer = Cache().userLoggedIn;
|
exerciseRepository.customer = Cache().userLoggedIn;
|
||||||
exerciseRepository.exerciseType = exerciseType;
|
exerciseRepository.exerciseType = exerciseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
double initQuantity;
|
|
||||||
double initUnitQuantity;
|
|
||||||
double quantity;
|
|
||||||
double unitQuantity;
|
|
||||||
double oneRepMax;
|
|
||||||
int step;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<TestSetControlState> mapEventToState(
|
Stream<TestSetControlState> mapEventToState(
|
||||||
TestSetControlEvent event,
|
TestSetControlEvent event,
|
||||||
|
@ -13,7 +13,7 @@ class TestSetControlLoad extends TestSetControlEvent {
|
|||||||
|
|
||||||
class TestSetControlQuantityChange extends TestSetControlEvent {
|
class TestSetControlQuantityChange extends TestSetControlEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const TestSetControlQuantityChange({this.quantity});
|
const TestSetControlQuantityChange({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -21,7 +21,7 @@ class TestSetControlQuantityChange extends TestSetControlEvent {
|
|||||||
|
|
||||||
class TestSetControlUnitQuantityChange extends TestSetControlEvent {
|
class TestSetControlUnitQuantityChange extends TestSetControlEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const TestSetControlUnitQuantityChange({this.quantity});
|
const TestSetControlUnitQuantityChange({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
|
@ -21,7 +21,7 @@ class TestSetControlReady extends TestSetControlState {
|
|||||||
|
|
||||||
class TestSetControlError extends TestSetControlState {
|
class TestSetControlError extends TestSetControlState {
|
||||||
final String message;
|
final String message;
|
||||||
const TestSetControlError({this.message});
|
const TestSetControlError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -21,14 +21,15 @@ part 'test_set_edit_state.dart';
|
|||||||
class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
||||||
final String templateName;
|
final String templateName;
|
||||||
final String templateNameTranslation;
|
final String templateNameTranslation;
|
||||||
String templateDescription;
|
late String templateDescription;
|
||||||
final WorkoutTreeRepository workoutTreeRepository;
|
final WorkoutTreeRepository workoutTreeRepository;
|
||||||
final MenuBloc menuBloc;
|
final MenuBloc menuBloc;
|
||||||
final List<ExerciseType> _exerciseTypes = List();
|
final List<ExerciseType> _exerciseTypes = [];
|
||||||
final List<ExerciseType> _actualExerciseTypes = List();
|
final List<ExerciseType> _actualExerciseTypes = [];
|
||||||
final HashMap<int, ExerciseType> _exercisePlanDetails = HashMap();
|
final HashMap<int, ExerciseType?> _exercisePlanDetails = HashMap();
|
||||||
|
|
||||||
TestSetEditBloc({this.templateName, this.templateNameTranslation, this.workoutTreeRepository, this.menuBloc})
|
TestSetEditBloc(
|
||||||
|
{required this.templateName, required this.templateNameTranslation, required this.workoutTreeRepository, required this.menuBloc})
|
||||||
: super(TestSetEditInitial()) {
|
: super(TestSetEditInitial()) {
|
||||||
if (Cache().exercisePlanTemplates.isNotEmpty) {
|
if (Cache().exercisePlanTemplates.isNotEmpty) {
|
||||||
Cache().exercisePlanTemplates.forEach((element) {
|
Cache().exercisePlanTemplates.forEach((element) {
|
||||||
@ -36,10 +37,12 @@ class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
|||||||
if (template.name == templateName) {
|
if (template.name == templateName) {
|
||||||
templateDescription = template.descriptionTranslation;
|
templateDescription = template.descriptionTranslation;
|
||||||
template.exerciseTypes.forEach((id) {
|
template.exerciseTypes.forEach((id) {
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(id);
|
final ExerciseType? exerciseType = Cache().getExerciseTypeById(id);
|
||||||
_exerciseTypes.add(exerciseType);
|
if (exerciseType != null) {
|
||||||
_actualExerciseTypes.add(exerciseType);
|
_exerciseTypes.add(exerciseType);
|
||||||
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
_actualExerciseTypes.add(exerciseType);
|
||||||
|
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -52,17 +55,18 @@ class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
|||||||
if (event is TestSetEditChangeExerciseType) {
|
if (event is TestSetEditChangeExerciseType) {
|
||||||
yield TestSetEditLoading();
|
yield TestSetEditLoading();
|
||||||
final List<ExerciseType> alternatives = workoutTreeRepository.getExerciseTypeAlternatives(event.exerciseTypeId);
|
final List<ExerciseType> alternatives = workoutTreeRepository.getExerciseTypeAlternatives(event.exerciseTypeId);
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId);
|
final ExerciseType? exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId);
|
||||||
|
if (exerciseType != null) {
|
||||||
if (_exercisePlanDetails[event.exerciseTypeId] == null) {
|
if (_exercisePlanDetails[event.exerciseTypeId] == null) {
|
||||||
/// it was skipped
|
/// it was skipped
|
||||||
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
|
||||||
} else {
|
|
||||||
if (event.index == 0) {
|
|
||||||
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
||||||
} else {
|
} else {
|
||||||
final changedExerciseType = alternatives[event.index - 1];
|
if (event.index == 0) {
|
||||||
_exercisePlanDetails[exerciseType.exerciseTypeId] = changedExerciseType;
|
_exercisePlanDetails[exerciseType.exerciseTypeId] = exerciseType;
|
||||||
|
} else {
|
||||||
|
final changedExerciseType = alternatives[event.index - 1];
|
||||||
|
_exercisePlanDetails[exerciseType.exerciseTypeId] = changedExerciseType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,28 +75,30 @@ class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
|||||||
yield TestSetEditReady();
|
yield TestSetEditReady();
|
||||||
} else if (event is TestSetEditDeleteExerciseType) {
|
} else if (event is TestSetEditDeleteExerciseType) {
|
||||||
yield TestSetEditLoading();
|
yield TestSetEditLoading();
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId);
|
final ExerciseType? exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId);
|
||||||
_exercisePlanDetails[exerciseType.exerciseTypeId] = null;
|
if (exerciseType != null) {
|
||||||
|
_exercisePlanDetails[exerciseType.exerciseTypeId] = null;
|
||||||
|
}
|
||||||
refreshActualPlan();
|
refreshActualPlan();
|
||||||
yield TestSetEditReady();
|
yield TestSetEditReady();
|
||||||
} else if (event is TestSetEditSubmit) {
|
} else if (event is TestSetEditSubmit) {
|
||||||
yield TestSetEditLoading();
|
yield TestSetEditLoading();
|
||||||
ExercisePlan exercisePlan = ExercisePlan(templateNameTranslation, Cache().userLoggedIn.customerId);
|
ExercisePlan exercisePlan = ExercisePlan(templateNameTranslation, Cache().userLoggedIn!.customerId!);
|
||||||
exercisePlan.private = true;
|
exercisePlan.private = true;
|
||||||
exercisePlan.type = ExerciseAbility.mini_test_set.enumToString();
|
exercisePlan.type = ExerciseAbility.mini_test_set.enumToString();
|
||||||
exercisePlan.dateAdd = DateTime.now();
|
exercisePlan.dateAdd = DateTime.now();
|
||||||
ExercisePlan savedExercisePlan = await ExercisePlanApi().saveExercisePlan(exercisePlan);
|
ExercisePlan savedExercisePlan = await ExercisePlanApi().saveExercisePlan(exercisePlan);
|
||||||
|
|
||||||
List<ExercisePlanDetail> details = List();
|
List<ExercisePlanDetail> details = [];
|
||||||
for (var entry in _exercisePlanDetails.entries) {
|
for (var entry in _exercisePlanDetails.entries) {
|
||||||
if (entry.value != null) {
|
if (entry.value != null) {
|
||||||
ExercisePlanDetail exercisePlanDetail = ExercisePlanDetail(entry.value.exerciseTypeId);
|
ExercisePlanDetail exercisePlanDetail = ExercisePlanDetail(entry.value!.exerciseTypeId);
|
||||||
exercisePlanDetail.exercisePlanId = savedExercisePlan.exercisePlanId;
|
exercisePlanDetail.exercisePlanId = savedExercisePlan.exercisePlanId!;
|
||||||
exercisePlanDetail.serie = 1;
|
exercisePlanDetail.serie = 1;
|
||||||
|
|
||||||
ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail);
|
ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail);
|
||||||
exercisePlanDetail.exercisePlanDetailId = savedDetail.exercisePlanDetailId;
|
exercisePlanDetail.exercisePlanDetailId = savedDetail.exercisePlanDetailId;
|
||||||
exercisePlanDetail.exercises = List();
|
exercisePlanDetail.exercises = [];
|
||||||
details.add(exercisePlanDetail);
|
details.add(exercisePlanDetail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,8 +118,10 @@ class TestSetEditBloc extends Bloc<TestSetEditEvent, TestSetEditState> {
|
|||||||
void refreshActualPlan() {
|
void refreshActualPlan() {
|
||||||
_actualExerciseTypes.removeRange(0, _actualExerciseTypes.length - 1);
|
_actualExerciseTypes.removeRange(0, _actualExerciseTypes.length - 1);
|
||||||
_exercisePlanDetails.keys.forEach((element) {
|
_exercisePlanDetails.keys.forEach((element) {
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(element);
|
final ExerciseType? exerciseType = Cache().getExerciseTypeById(element);
|
||||||
_actualExerciseTypes.add(exerciseType);
|
if (exerciseType != null) {
|
||||||
|
_actualExerciseTypes.add(exerciseType);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ class TestSetEditLoad extends TestSetEditEvent {
|
|||||||
class TestSetEditChangeExerciseType extends TestSetEditEvent {
|
class TestSetEditChangeExerciseType extends TestSetEditEvent {
|
||||||
final int index;
|
final int index;
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetEditChangeExerciseType({this.index, this.exerciseTypeId});
|
const TestSetEditChangeExerciseType({required this.index, required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [index, exerciseTypeId];
|
List<Object> get props => [index, exerciseTypeId];
|
||||||
@ -22,7 +22,7 @@ class TestSetEditChangeExerciseType extends TestSetEditEvent {
|
|||||||
|
|
||||||
class TestSetEditDeleteExerciseType extends TestSetEditEvent {
|
class TestSetEditDeleteExerciseType extends TestSetEditEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetEditDeleteExerciseType({this.exerciseTypeId});
|
const TestSetEditDeleteExerciseType({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
@ -30,7 +30,7 @@ class TestSetEditDeleteExerciseType extends TestSetEditEvent {
|
|||||||
|
|
||||||
class TestSetEditSkipExerciseType extends TestSetEditEvent {
|
class TestSetEditSkipExerciseType extends TestSetEditEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetEditSkipExerciseType({this.exerciseTypeId});
|
const TestSetEditSkipExerciseType({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
|
@ -25,7 +25,7 @@ class TestSetEditLoading extends TestSetEditState {
|
|||||||
|
|
||||||
class TestSetEditError extends TestSetEditState {
|
class TestSetEditError extends TestSetEditState {
|
||||||
final String message;
|
final String message;
|
||||||
const TestSetEditError({this.message});
|
const TestSetEditError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -18,17 +18,17 @@ part 'test_set_execute_state.dart';
|
|||||||
|
|
||||||
class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState> {
|
class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState> {
|
||||||
// ignore: close_sinks
|
// ignore: close_sinks
|
||||||
MenuBloc menuBloc;
|
late MenuBloc menuBloc;
|
||||||
int exerciseTypeId;
|
int? exerciseTypeId;
|
||||||
String testName;
|
String? testName;
|
||||||
String testType = "";
|
String testType = "";
|
||||||
bool miniTestSet = false;
|
bool miniTestSet = false;
|
||||||
bool paralellTest = false;
|
bool paralellTest = false;
|
||||||
double scrollOffset = 0;
|
double scrollOffset = 0;
|
||||||
ExercisePlan exercisePlan;
|
ExercisePlan? exercisePlan;
|
||||||
bool isDone100 = false;
|
bool isDone100 = false;
|
||||||
|
|
||||||
List<ExercisePlanDetail> exercisePlanDetails;
|
List<ExercisePlanDetail>? exercisePlanDetails;
|
||||||
|
|
||||||
TestSetExecuteBloc() : super(TestSetExecuteInitial());
|
TestSetExecuteBloc() : super(TestSetExecuteInitial());
|
||||||
|
|
||||||
@ -37,19 +37,19 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
void initExercisePlan() {
|
void initExercisePlan() {
|
||||||
exercisePlan = Cache().activeExercisePlan;
|
exercisePlan = Cache().activeExercisePlan;
|
||||||
if (exercisePlan != null) {
|
if (exercisePlan != null) {
|
||||||
testName = exercisePlan.name;
|
testName = exercisePlan!.name;
|
||||||
this.miniTestSet = exercisePlan.type != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan.type);
|
this.miniTestSet = exercisePlan!.type != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan!.type!);
|
||||||
this.paralellTest = exercisePlan.type != null && ExerciseAbility.paralell_test.equalsStringTo(exercisePlan.type);
|
this.paralellTest = exercisePlan!.type != null && ExerciseAbility.paralell_test.equalsStringTo(exercisePlan!.type!);
|
||||||
|
|
||||||
testType = ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan.type)
|
testType = ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan!.type!)
|
||||||
? ExerciseAbility.mini_test_set.description
|
? ExerciseAbility.mini_test_set.description
|
||||||
: ExerciseAbility.paralell_test.description;
|
: ExerciseAbility.paralell_test.description;
|
||||||
print("exercisePlan: $testName type: $testType");
|
print("exercisePlan: $testName type: $testType");
|
||||||
}
|
}
|
||||||
exercisePlanDetails = Cache().activeExercisePlanDetails;
|
exercisePlanDetails = Cache().activeExercisePlanDetails;
|
||||||
if (exercisePlanDetails != null) {
|
if (exercisePlanDetails != null) {
|
||||||
exercisePlanDetails.forEach((element) {
|
exercisePlanDetails!.forEach((element) {
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(element.exerciseTypeId);
|
final ExerciseType? exerciseType = Cache().getExerciseTypeById(element.exerciseTypeId);
|
||||||
if (exerciseType != null) {
|
if (exerciseType != null) {
|
||||||
element.exerciseType = exerciseType;
|
element.exerciseType = exerciseType;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
if (exerciseTypeId != null) {
|
if (exerciseTypeId != null) {
|
||||||
int step = 0;
|
int step = 0;
|
||||||
if (exercisePlanDetails != null) {
|
if (exercisePlanDetails != null) {
|
||||||
exercisePlanDetails.forEach((element) {
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (element.exerciseTypeId == this.exerciseTypeId) {
|
if (element.exerciseTypeId == this.exerciseTypeId) {
|
||||||
scrollOffset = (step * 85).toDouble() + 10;
|
scrollOffset = (step * 85).toDouble() + 10;
|
||||||
}
|
}
|
||||||
@ -79,44 +79,44 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
}
|
}
|
||||||
yield TestSetExecuteReady();
|
yield TestSetExecuteReady();
|
||||||
} else if (event is TestSetExecuteDeleteActive) {
|
} else if (event is TestSetExecuteDeleteActive) {
|
||||||
print("Delete: ${exercisePlan.type} paralellTest: $paralellTest");
|
print("Delete: ${exercisePlan!.type} paralellTest: $paralellTest");
|
||||||
if (exercisePlan != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan.type)) {
|
if (exercisePlan != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan!.type!)) {
|
||||||
exercisePlan = null;
|
exercisePlan = null;
|
||||||
if (exercisePlanDetails != null) {
|
if (exercisePlanDetails != null) {
|
||||||
exercisePlanDetails.removeRange(0, exercisePlanDetails.length - 1);
|
exercisePlanDetails!.removeRange(0, exercisePlanDetails!.length - 1);
|
||||||
}
|
}
|
||||||
await Cache().deleteActiveExercisePlan();
|
await Cache().deleteActiveExercisePlan();
|
||||||
}
|
}
|
||||||
} else if (event is TestSetExecuteDeleteAllActive) {
|
} else if (event is TestSetExecuteDeleteAllActive) {
|
||||||
print("DeleteAll Test Set: ${exercisePlan.type}");
|
|
||||||
if (exercisePlan != null) {
|
if (exercisePlan != null) {
|
||||||
|
print("DeleteAll Test Set: ${exercisePlan!.type}");
|
||||||
exercisePlan = null;
|
exercisePlan = null;
|
||||||
if (exercisePlanDetails != null) {
|
if (exercisePlanDetails != null) {
|
||||||
exercisePlanDetails.removeRange(0, exercisePlanDetails.length - 1);
|
exercisePlanDetails!.removeRange(0, exercisePlanDetails!.length - 1);
|
||||||
}
|
}
|
||||||
await Cache().deleteActiveExercisePlan();
|
await Cache().deleteActiveExercisePlan();
|
||||||
}
|
}
|
||||||
} else if (event is TestSetExecuteExerciseFinished) {
|
} else if (event is TestSetExecuteExerciseFinished) {
|
||||||
yield TestSetExecuteLoading();
|
yield TestSetExecuteLoading();
|
||||||
exercisePlanDetails.forEach((element) {
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (element.exerciseTypeId == event.exerciseTypeId) {
|
if (element.exerciseTypeId == event.exerciseTypeId) {
|
||||||
element.repeats = event.quantity.toInt();
|
element.repeats = event.quantity.toInt();
|
||||||
element.weightEquation = event.unitQuantity.toString();
|
element.weightEquation = event.unitQuantity.toString();
|
||||||
if (element.exercises == null) {
|
if (element.exercises == null) {
|
||||||
element.exercises = List();
|
element.exercises = [];
|
||||||
}
|
}
|
||||||
final Exercise exercise = Exercise();
|
final Exercise exercise = Exercise();
|
||||||
exercise.customerId = Cache().userLoggedIn.customerId;
|
exercise.customerId = Cache().userLoggedIn!.customerId!;
|
||||||
exercise.exerciseTypeId = event.exerciseTypeId;
|
exercise.exerciseTypeId = event.exerciseTypeId;
|
||||||
exercise.quantity = event.quantity;
|
exercise.quantity = event.quantity;
|
||||||
exercise.unit = element.exerciseType.unit;
|
exercise.unit = element.exerciseType!.unit;
|
||||||
exercise.unitQuantity = event.unitQuantity;
|
exercise.unitQuantity = event.unitQuantity;
|
||||||
exercise.dateAdd = DateTime.now();
|
exercise.dateAdd = DateTime.now();
|
||||||
element.exercises.add(exercise);
|
element.exercises!.add(exercise);
|
||||||
setPlanDetailState(element);
|
setPlanDetailState(element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Cache().saveActiveExercisePlan(exercisePlan, exercisePlanDetails);
|
Cache().saveActiveExercisePlan(exercisePlan!, exercisePlanDetails!);
|
||||||
if (this.isDone100Percent()) {
|
if (this.isDone100Percent()) {
|
||||||
add(TestSetExecuteFinish());
|
add(TestSetExecuteFinish());
|
||||||
} else {
|
} else {
|
||||||
@ -125,45 +125,51 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
} else if (event is TestSetExecuteNewExercise) {
|
} else if (event is TestSetExecuteNewExercise) {
|
||||||
yield TestSetExecuteLoading();
|
yield TestSetExecuteLoading();
|
||||||
if (exercisePlan == null) {
|
if (exercisePlan == null) {
|
||||||
exercisePlan = ExercisePlan(Cache().userLoggedIn.name + " Custom Test", Cache().userLoggedIn.customerId);
|
exercisePlan = ExercisePlan(Cache().userLoggedIn!.name! + " Custom Test", Cache().userLoggedIn!.customerId!);
|
||||||
exercisePlan.private = true;
|
exercisePlan!.private = true;
|
||||||
exercisePlan.dateAdd = DateTime.now();
|
exercisePlan!.dateAdd = DateTime.now();
|
||||||
exercisePlan.type = ExerciseAbility.paralell_test.enumToString();
|
exercisePlan!.type = ExerciseAbility.paralell_test.enumToString();
|
||||||
ExercisePlan savedExercisePlan = await ExercisePlanApi().saveExercisePlan(exercisePlan);
|
ExercisePlan savedExercisePlan = await ExercisePlanApi().saveExercisePlan(exercisePlan!);
|
||||||
exercisePlan = savedExercisePlan;
|
exercisePlan = savedExercisePlan;
|
||||||
exercisePlanDetails = List();
|
exercisePlanDetails = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.existsInPlanDetails(event.exerciseTypeId)) {
|
if (!this.existsInPlanDetails(event.exerciseTypeId)) {
|
||||||
ExercisePlanDetail exercisePlanDetail = ExercisePlanDetail(event.exerciseTypeId);
|
ExercisePlanDetail exercisePlanDetail = ExercisePlanDetail(event.exerciseTypeId);
|
||||||
exercisePlanDetail.exercisePlanId = exercisePlan.exercisePlanId;
|
exercisePlanDetail.exercisePlanId = exercisePlan!.exercisePlanId!;
|
||||||
final ExerciseType exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId);
|
final ExerciseType exerciseType = Cache().getExerciseTypeById(event.exerciseTypeId)!;
|
||||||
|
|
||||||
exercisePlanDetail.serie = exerciseType.unitQuantityUnit == null ? 1 : 4;
|
exercisePlanDetail.serie = exerciseType.unitQuantityUnit == null ? 1 : 4;
|
||||||
exercisePlanDetail.exerciseType = exerciseType;
|
exercisePlanDetail.exerciseType = exerciseType;
|
||||||
exercisePlanDetail.exerciseTypeId = event.exerciseTypeId;
|
exercisePlanDetail.exerciseTypeId = event.exerciseTypeId;
|
||||||
ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail);
|
ExercisePlanDetail savedDetail = await ExercisePlanApi().saveExercisePlanDetail(exercisePlanDetail);
|
||||||
exercisePlanDetail.exercisePlanDetailId = savedDetail.exercisePlanDetailId;
|
exercisePlanDetail.exercisePlanDetailId = savedDetail.exercisePlanDetailId;
|
||||||
exercisePlanDetail.state = ExercisePlanDetailState.start;
|
exercisePlanDetail.state = ExercisePlanDetailState.start;
|
||||||
exercisePlanDetail.exercises = List();
|
exercisePlanDetail.exercises = [];
|
||||||
exercisePlanDetails.add(exercisePlanDetail);
|
if (exercisePlanDetails == null) {
|
||||||
await Cache().saveActiveExercisePlan(exercisePlan, exercisePlanDetails);
|
exercisePlanDetails = [];
|
||||||
|
}
|
||||||
|
exercisePlanDetails!.add(exercisePlanDetail);
|
||||||
|
await Cache().saveActiveExercisePlan(exercisePlan!, exercisePlanDetails!);
|
||||||
paralellTest = true;
|
paralellTest = true;
|
||||||
}
|
}
|
||||||
yield TestSetExecuteReady();
|
yield TestSetExecuteReady();
|
||||||
} else if (event is TestSetExecuteDeleteExercise) {
|
} else if (event is TestSetExecuteDeleteExercise) {
|
||||||
yield TestSetExecuteLoading();
|
yield TestSetExecuteLoading();
|
||||||
ExercisePlanDetail deleteDetail;
|
ExercisePlanDetail? deleteDetail;
|
||||||
exercisePlanDetails.forEach((element) {
|
if (exercisePlanDetails != null) {
|
||||||
if (element.exerciseTypeId == event.exerciseTypeId) {
|
exercisePlanDetails!.forEach((element) {
|
||||||
deleteDetail = element;
|
if (element.exerciseTypeId == event.exerciseTypeId) {
|
||||||
}
|
deleteDetail = element;
|
||||||
});
|
}
|
||||||
if (deleteDetail != null) {
|
});
|
||||||
exercisePlanDetails.remove(deleteDetail);
|
if (deleteDetail != null) {
|
||||||
if (exercisePlanDetails.isEmpty) {
|
exercisePlanDetails!.remove(deleteDetail);
|
||||||
exercisePlan = null;
|
if (exercisePlanDetails!.isEmpty) {
|
||||||
exercisePlanDetails = null;
|
exercisePlan = null;
|
||||||
Cache().deleteActiveExercisePlan();
|
exercisePlanDetails = null;
|
||||||
|
Cache().deleteActiveExercisePlan();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield TestSetExecuteReady();
|
yield TestSetExecuteReady();
|
||||||
@ -181,9 +187,9 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
bool hasBegun() {
|
bool hasBegun() {
|
||||||
if (exercisePlanDetails == null ||
|
if (exercisePlanDetails == null ||
|
||||||
exercisePlanDetails.isEmpty ||
|
exercisePlanDetails!.isEmpty ||
|
||||||
exercisePlanDetails[0].exercises == null ||
|
exercisePlanDetails![0].exercises == null ||
|
||||||
exercisePlanDetails[0].exercises.length == 0) {
|
exercisePlanDetails![0].exercises!.length == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,14 +197,14 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setPlanDetailState(ExercisePlanDetail exercisePlanDetail) {
|
void setPlanDetailState(ExercisePlanDetail exercisePlanDetail) {
|
||||||
if (exercisePlanDetail.exercises == null || exercisePlanDetail.exercises.length == 0) {
|
if (exercisePlanDetail.exercises == null || exercisePlanDetail.exercises!.length == 0) {
|
||||||
exercisePlanDetail.state = ExercisePlanDetailState.start;
|
exercisePlanDetail.state = ExercisePlanDetailState.start;
|
||||||
} else {
|
} else {
|
||||||
int maxLength = 1;
|
int maxLength = 1;
|
||||||
if (exercisePlanDetail.exerciseType.unitQuantityUnit != null) {
|
if (exercisePlanDetail.exerciseType!.unitQuantityUnit != null) {
|
||||||
maxLength = 4;
|
maxLength = 4;
|
||||||
}
|
}
|
||||||
if (exercisePlanDetail.exercises.length >= maxLength) {
|
if (exercisePlanDetail.exercises!.length >= maxLength) {
|
||||||
exercisePlanDetail.state = ExercisePlanDetailState.finished;
|
exercisePlanDetail.state = ExercisePlanDetailState.finished;
|
||||||
} else {
|
} else {
|
||||||
exercisePlanDetail.state = ExercisePlanDetailState.inProgress;
|
exercisePlanDetail.state = ExercisePlanDetailState.inProgress;
|
||||||
@ -208,7 +214,8 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
ExercisePlanDetailState actualState(int exerciseTypeId) {
|
ExercisePlanDetailState actualState(int exerciseTypeId) {
|
||||||
ExercisePlanDetailState state = ExercisePlanDetailState.start;
|
ExercisePlanDetailState state = ExercisePlanDetailState.start;
|
||||||
exercisePlanDetails.forEach((element) {
|
if (exercisePlanDetails == null) return state;
|
||||||
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (element.exerciseTypeId == exerciseTypeId) {
|
if (element.exerciseTypeId == exerciseTypeId) {
|
||||||
state = element.state;
|
state = element.state;
|
||||||
}
|
}
|
||||||
@ -218,7 +225,8 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
bool existsInPlanDetails(int exerciseTypeId) {
|
bool existsInPlanDetails(int exerciseTypeId) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
exercisePlanDetails.forEach((element) {
|
if (exercisePlanDetails == null) return found;
|
||||||
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (element.exerciseTypeId == exerciseTypeId) {
|
if (element.exerciseTypeId == exerciseTypeId) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
@ -226,9 +234,11 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExercisePlanDetail actualExercisePlanDetail(int exerciseTypeId) {
|
ExercisePlanDetail? actualExercisePlanDetail(int exerciseTypeId) {
|
||||||
ExercisePlanDetail found;
|
ExercisePlanDetail? found;
|
||||||
exercisePlanDetails.forEach((element) {
|
if (exercisePlanDetails == null) return found;
|
||||||
|
|
||||||
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (element.exerciseTypeId == exerciseTypeId) {
|
if (element.exerciseTypeId == exerciseTypeId) {
|
||||||
found = element;
|
found = element;
|
||||||
}
|
}
|
||||||
@ -238,10 +248,10 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
bool isDone100Percent() {
|
bool isDone100Percent() {
|
||||||
bool done = true;
|
bool done = true;
|
||||||
if (exercisePlanDetails == null || exercisePlanDetails.isEmpty) {
|
if (exercisePlanDetails == null || exercisePlanDetails!.isEmpty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
exercisePlanDetails.forEach((element) {
|
exercisePlanDetails!.forEach((element) {
|
||||||
if (!element.state.equalsTo(ExercisePlanDetailState.finished)) {
|
if (!element.state.equalsTo(ExercisePlanDetailState.finished)) {
|
||||||
done = false;
|
done = false;
|
||||||
}
|
}
|
||||||
@ -251,7 +261,7 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
HashMap canAddNewExercise() {
|
HashMap canAddNewExercise() {
|
||||||
HashMap ret = HashMap();
|
HashMap ret = HashMap();
|
||||||
if (exercisePlan != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan.type)) {
|
if (exercisePlan != null && ExerciseAbility.mini_test_set.equalsStringTo(exercisePlan!.type!)) {
|
||||||
final String message = "You have an active Test Set!";
|
final String message = "You have an active Test Set!";
|
||||||
final String message2 = "Do you want you to override it?";
|
final String message2 = "Do you want you to override it?";
|
||||||
ret['message'] = message;
|
ret['message'] = message;
|
||||||
@ -264,8 +274,8 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getActualWorkoutTreeId(int exerciseTypeId) {
|
int? getActualWorkoutTreeId(int exerciseTypeId) {
|
||||||
final WorkoutMenuTree workoutTree = this.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseTypeId);
|
final WorkoutMenuTree? workoutTree = this.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseTypeId);
|
||||||
if (workoutTree == null) {
|
if (workoutTree == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -276,7 +286,7 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
if (exerciseTypeId <= 0) {
|
if (exerciseTypeId <= 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
final WorkoutMenuTree workoutTree = this.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseTypeId);
|
final WorkoutMenuTree? workoutTree = this.menuBloc.menuTreeRepository.getMenuItemByExerciseTypeId(exerciseTypeId);
|
||||||
if (workoutTree == null) {
|
if (workoutTree == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -288,14 +298,14 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
if (exercisePlanDetails == null) {
|
if (exercisePlanDetails == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (exercisePlanDetails.isEmpty) {
|
if (exercisePlanDetails!.isEmpty) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (exercisePlanDetails[0].exercises == null || exercisePlanDetails[0].exercises.length == 0);
|
return (exercisePlanDetails![0].exercises == null || exercisePlanDetails![0].exercises!.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool existsActivePlan() {
|
bool existsActivePlan() {
|
||||||
final bool exists = exercisePlan != null && exercisePlanDetails.length > 0;
|
final bool exists = exercisePlan != null && exercisePlanDetails != null && exercisePlanDetails!.isNotEmpty;
|
||||||
print("Exists active plan: $exists");
|
print("Exists active plan: $exists");
|
||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
@ -304,20 +314,22 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
return (exercisePlanDetail.state.equalsTo(ExercisePlanDetailState.finished));
|
return (exercisePlanDetail.state.equalsTo(ExercisePlanDetailState.finished));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExercisePlanDetail getNext() {
|
ExercisePlanDetail? getNext() {
|
||||||
ExercisePlanDetail nextExercisePlanDetail;
|
ExercisePlanDetail? nextExercisePlanDetail;
|
||||||
int minStep = 99;
|
int minStep = 99;
|
||||||
for (final detail in this.exercisePlanDetails) {
|
if (this.exercisePlanDetails == null) {
|
||||||
if (!detail.state.equalsTo(ExercisePlanDetailState.finished)) {
|
for (final detail in this.exercisePlanDetails!) {
|
||||||
if (detail.exercises == null) {
|
if (!detail.state.equalsTo(ExercisePlanDetailState.finished)) {
|
||||||
nextExercisePlanDetail = detail;
|
if (detail.exercises == null) {
|
||||||
minStep = 1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
final int step = detail.exercises.length;
|
|
||||||
if (step < minStep) {
|
|
||||||
nextExercisePlanDetail = detail;
|
nextExercisePlanDetail = detail;
|
||||||
minStep = step;
|
minStep = 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
final int step = detail.exercises!.length;
|
||||||
|
if (step < minStep) {
|
||||||
|
nextExercisePlanDetail = detail;
|
||||||
|
minStep = step;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,10 +353,10 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
String repeatTimesText(ExercisePlanDetail exercisePlanDetail) {
|
String repeatTimesText(ExercisePlanDetail exercisePlanDetail) {
|
||||||
String text = "maximum";
|
String text = "maximum";
|
||||||
if (!hasBegun() || exercisePlanDetail.exerciseType.unitQuantityUnit == null) {
|
if (!hasBegun() || exercisePlanDetail.exerciseType!.unitQuantityUnit == null) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
int step = exercisePlanDetail.exercises.length;
|
int step = exercisePlanDetail.exercises!.length;
|
||||||
print("repeatTimes step $step");
|
print("repeatTimes step $step");
|
||||||
if (step == 2) {
|
if (step == 2) {
|
||||||
text = "12";
|
text = "12";
|
||||||
@ -354,13 +366,13 @@ class TestSetExecuteBloc extends Bloc<TestSetExecuteEvent, TestSetExecuteState>
|
|||||||
|
|
||||||
String getExerciseWeight(ExercisePlanDetail exercisePlanDetail) {
|
String getExerciseWeight(ExercisePlanDetail exercisePlanDetail) {
|
||||||
String text = "you are able to do 12-20 repeats with";
|
String text = "you are able to do 12-20 repeats with";
|
||||||
if (!hasBegun() || exercisePlanDetail.exercises.length < 2) {
|
if (!hasBegun() || exercisePlanDetail.exercises!.length < 2) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
final double unitQuantity = exercisePlanDetail.exercises.last.unitQuantity;
|
final double unitQuantity = exercisePlanDetail.exercises!.last.unitQuantity;
|
||||||
final double quantity = exercisePlanDetail.exercises.last.quantity;
|
final double quantity = exercisePlanDetail.exercises!.last.quantity;
|
||||||
double oneRepMax = this.calculate1RM(quantity, unitQuantity);
|
double oneRepMax = this.calculate1RM(quantity, unitQuantity);
|
||||||
text = (oneRepMax * 0.75).round().toStringAsFixed(0) + " " + exercisePlanDetail.exerciseType.unitQuantityUnit;
|
text = (oneRepMax * 0.75).round().toStringAsFixed(0) + " " + exercisePlanDetail.exerciseType!.unitQuantityUnit!;
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ class TestSetExecuteLoad extends TestSetExecuteEvent {
|
|||||||
|
|
||||||
class TestSetExecuteExecute extends TestSetExecuteEvent {
|
class TestSetExecuteExecute extends TestSetExecuteEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetExecuteExecute({this.exerciseTypeId});
|
const TestSetExecuteExecute({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
@ -27,7 +27,7 @@ class TestSetExecuteExerciseFinished extends TestSetExecuteEvent {
|
|||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
final double quantity;
|
final double quantity;
|
||||||
final double unitQuantity;
|
final double unitQuantity;
|
||||||
const TestSetExecuteExerciseFinished({this.exerciseTypeId, this.quantity, this.unitQuantity});
|
const TestSetExecuteExerciseFinished({required this.exerciseTypeId, required this.quantity, required this.unitQuantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId, quantity, unitQuantity];
|
List<Object> get props => [exerciseTypeId, quantity, unitQuantity];
|
||||||
@ -35,7 +35,7 @@ class TestSetExecuteExerciseFinished extends TestSetExecuteEvent {
|
|||||||
|
|
||||||
class TestSetExecuteNewExercise extends TestSetExecuteEvent {
|
class TestSetExecuteNewExercise extends TestSetExecuteEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetExecuteNewExercise({this.exerciseTypeId});
|
const TestSetExecuteNewExercise({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
@ -43,7 +43,7 @@ class TestSetExecuteNewExercise extends TestSetExecuteEvent {
|
|||||||
|
|
||||||
class TestSetExecuteDeleteExercise extends TestSetExecuteEvent {
|
class TestSetExecuteDeleteExercise extends TestSetExecuteEvent {
|
||||||
final int exerciseTypeId;
|
final int exerciseTypeId;
|
||||||
const TestSetExecuteDeleteExercise({this.exerciseTypeId});
|
const TestSetExecuteDeleteExercise({required this.exerciseTypeId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [exerciseTypeId];
|
List<Object> get props => [exerciseTypeId];
|
||||||
|
@ -25,7 +25,7 @@ class TestSetExecuteReady extends TestSetExecuteState {
|
|||||||
|
|
||||||
class TestSetExecuteError extends TestSetExecuteState {
|
class TestSetExecuteError extends TestSetExecuteState {
|
||||||
final String message;
|
final String message;
|
||||||
const TestSetExecuteError({this.message});
|
const TestSetExecuteError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -18,21 +18,23 @@ class TestSetNewBloc extends Bloc<TestSetNewEvent, TestSetNewState> {
|
|||||||
final int exercisePlanDetailId;
|
final int exercisePlanDetailId;
|
||||||
final TestSetExecuteBloc executeBloc;
|
final TestSetExecuteBloc executeBloc;
|
||||||
|
|
||||||
TestSetNewBloc({this.exerciseRepository, this.exerciseType, this.exercisePlanDetailId, this.executeBloc}) : super(TestSetNewInitial()) {
|
late double quantity;
|
||||||
|
late double unitQuantity;
|
||||||
|
|
||||||
|
TestSetNewBloc(
|
||||||
|
{required this.exerciseRepository, required this.exerciseType, required this.exercisePlanDetailId, required this.executeBloc})
|
||||||
|
: super(TestSetNewInitial()) {
|
||||||
exerciseRepository.exerciseType = exerciseType;
|
exerciseRepository.exerciseType = exerciseType;
|
||||||
quantity = 12;
|
quantity = 12;
|
||||||
unitQuantity = 30;
|
unitQuantity = 30;
|
||||||
exerciseRepository.setQuantity(quantity);
|
exerciseRepository.setQuantity(quantity);
|
||||||
exerciseRepository.setUnit(exerciseType.unit);
|
exerciseRepository.setUnit(exerciseType.unit);
|
||||||
exerciseRepository.setUnitQuantity(unitQuantity);
|
exerciseRepository.setUnitQuantity(unitQuantity);
|
||||||
exerciseRepository.exercise.exercisePlanDetailId = exercisePlanDetailId;
|
exerciseRepository.exercise!.exercisePlanDetailId = exercisePlanDetailId;
|
||||||
exerciseRepository.start = DateTime.now();
|
exerciseRepository.start = DateTime.now();
|
||||||
exerciseRepository.setCustomer(Cache().userLoggedIn);
|
exerciseRepository.setCustomer(Cache().userLoggedIn!);
|
||||||
}
|
}
|
||||||
|
|
||||||
double quantity;
|
|
||||||
double unitQuantity;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Stream<TestSetNewState> mapEventToState(
|
Stream<TestSetNewState> mapEventToState(
|
||||||
TestSetNewEvent event,
|
TestSetNewEvent event,
|
||||||
|
@ -13,7 +13,7 @@ class TestSetNewLoad extends TestSetNewEvent {
|
|||||||
|
|
||||||
class TestSetNewChangeQuantity extends TestSetNewEvent {
|
class TestSetNewChangeQuantity extends TestSetNewEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const TestSetNewChangeQuantity({this.quantity});
|
const TestSetNewChangeQuantity({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
@ -21,7 +21,7 @@ class TestSetNewChangeQuantity extends TestSetNewEvent {
|
|||||||
|
|
||||||
class TestSetNewChangeQuantityUnit extends TestSetNewEvent {
|
class TestSetNewChangeQuantityUnit extends TestSetNewEvent {
|
||||||
final double quantity;
|
final double quantity;
|
||||||
const TestSetNewChangeQuantityUnit({this.quantity});
|
const TestSetNewChangeQuantityUnit({required this.quantity});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [quantity];
|
List<Object> get props => [quantity];
|
||||||
|
@ -21,7 +21,7 @@ class TestSetNewReady extends TestSetNewState {
|
|||||||
|
|
||||||
class TestSetNewError extends TestSetNewState {
|
class TestSetNewError extends TestSetNewState {
|
||||||
final String message;
|
final String message;
|
||||||
const TestSetNewError({this.message});
|
const TestSetNewError({required this.message});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [message];
|
List<Object> get props => [message];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:audioplayer/audioplayer.dart';
|
//import 'package:audioplayer/audioplayer.dart';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
@ -8,7 +8,7 @@ part 'timer_event.dart';
|
|||||||
part 'timer_state.dart';
|
part 'timer_state.dart';
|
||||||
|
|
||||||
class Ticker {
|
class Ticker {
|
||||||
Stream<int> tick({int ticks}) {
|
Stream<int> tick({required int ticks}) {
|
||||||
return Stream.periodic(Duration(seconds: 1), (x) => compute(ticks, x)).take(ticks);
|
return Stream.periodic(Duration(seconds: 1), (x) => compute(ticks, x)).take(ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,11 +22,12 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
|
|||||||
final Ticker _ticker = Ticker();
|
final Ticker _ticker = Ticker();
|
||||||
int _duration = 0;
|
int _duration = 0;
|
||||||
|
|
||||||
final AudioPlayer audioPlayer = AudioPlayer();
|
//final AudioPlayer audioPlayer = AudioPlayer();
|
||||||
int minutes = 0;
|
int minutes = 0;
|
||||||
int seconds = 0;
|
int seconds = 0;
|
||||||
|
|
||||||
StreamSubscription<int> _tickerSubscription;
|
// ignore: cancel_subscriptions
|
||||||
|
StreamSubscription<int>? _tickerSubscription;
|
||||||
|
|
||||||
TimerBloc() : super(TimerReady(300));
|
TimerBloc() : super(TimerReady(300));
|
||||||
|
|
||||||
@ -52,21 +53,27 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
|
|||||||
yield* _mapTickToState(event);
|
yield* _mapTickToState(event);
|
||||||
} else if (event is TimerEnd) {
|
} else if (event is TimerEnd) {
|
||||||
print("$event");
|
print("$event");
|
||||||
_tickerSubscription?.cancel();
|
if (_tickerSubscription != null) {
|
||||||
|
_tickerSubscription!.cancel();
|
||||||
|
}
|
||||||
yield TimerFinished(state.duration);
|
yield TimerFinished(state.duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_tickerSubscription?.cancel();
|
if (_tickerSubscription != null) {
|
||||||
|
_tickerSubscription!.cancel();
|
||||||
|
}
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<TimerState> _mapStartToState(TimerStart start) async* {
|
Stream<TimerState> _mapStartToState(TimerStart start) async* {
|
||||||
//print("$start");
|
//print("$start");
|
||||||
yield TimerRunning(start.duration);
|
yield TimerRunning(start.duration);
|
||||||
_tickerSubscription?.cancel();
|
if (_tickerSubscription != null) {
|
||||||
|
_tickerSubscription!.cancel();
|
||||||
|
}
|
||||||
_tickerSubscription = _ticker.tick(ticks: start.duration).listen(
|
_tickerSubscription = _ticker.tick(ticks: start.duration).listen(
|
||||||
(localDuration) {
|
(localDuration) {
|
||||||
//print("local: $localDuration");
|
//print("local: $localDuration");
|
||||||
@ -77,14 +84,19 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
|
|||||||
|
|
||||||
Stream<TimerState> _mapPauseToState(TimerPause pause) async* {
|
Stream<TimerState> _mapPauseToState(TimerPause pause) async* {
|
||||||
if (state is TimerRunning) {
|
if (state is TimerRunning) {
|
||||||
_tickerSubscription?.pause();
|
if (_tickerSubscription != null) {
|
||||||
|
_tickerSubscription!.pause();
|
||||||
|
}
|
||||||
yield TimerPaused(state.duration);
|
yield TimerPaused(state.duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream<TimerState> _mapResumeToState(TimerResume pause) async* {
|
Stream<TimerState> _mapResumeToState(TimerResume pause) async* {
|
||||||
if (state is TimerPaused) {
|
if (state is TimerPaused) {
|
||||||
_tickerSubscription?.resume();
|
if (_tickerSubscription != null) {
|
||||||
|
_tickerSubscription!.resume();
|
||||||
|
}
|
||||||
|
|
||||||
yield TimerRunning(state.duration);
|
yield TimerRunning(state.duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,7 +112,7 @@ class TimerBloc extends Bloc<TimerEvent, TimerState> {
|
|||||||
yield tick.duration >= 0 ? TimerRunning(tick.duration) : TimerFinished(tick.duration);
|
yield tick.duration >= 0 ? TimerRunning(tick.duration) : TimerFinished(tick.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _play() async {
|
/* Future _play() async {
|
||||||
await audioPlayer.play('asset/wine-glass.mp3', isLocal: true);
|
await audioPlayer.play('asset/wine-glass.mp3', isLocal: true);
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ abstract class TimerEvent extends Equatable {
|
|||||||
|
|
||||||
class TimerStart extends TimerEvent {
|
class TimerStart extends TimerEvent {
|
||||||
final int duration;
|
final int duration;
|
||||||
const TimerStart({this.duration});
|
const TimerStart({required this.duration});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => "TimerStart { duration: $duration }";
|
String toString() => "TimerStart { duration: $duration }";
|
||||||
@ -17,12 +17,12 @@ class TimerStart extends TimerEvent {
|
|||||||
|
|
||||||
class TimerEnd extends TimerEvent {
|
class TimerEnd extends TimerEvent {
|
||||||
final int duration;
|
final int duration;
|
||||||
const TimerEnd({this.duration});
|
const TimerEnd({required this.duration});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TimerTick extends TimerEvent {
|
class TimerTick extends TimerEvent {
|
||||||
final int duration;
|
final int duration;
|
||||||
const TimerTick({this.duration});
|
const TimerTick({required this.duration});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => "Tick { duration: $duration }";
|
String toString() => "Tick { duration: $duration }";
|
||||||
|
@ -45,5 +45,5 @@ class TimerFinished extends TimerState {
|
|||||||
|
|
||||||
class TimerError extends TimerState {
|
class TimerError extends TimerState {
|
||||||
final String message;
|
final String message;
|
||||||
TimerError(int duration, {this.message}) : super(duration);
|
TimerError(int duration, {required this.message}) : super(duration);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import 'package:sqflite/sqflite.dart';
|
|||||||
class DB {
|
class DB {
|
||||||
static final DB _singleton = DB._internal();
|
static final DB _singleton = DB._internal();
|
||||||
String dbName = "workouttest.db";
|
String dbName = "workouttest.db";
|
||||||
Database _db;
|
late Database _db;
|
||||||
|
|
||||||
factory DB() {
|
factory DB() {
|
||||||
return _singleton;
|
return _singleton;
|
||||||
@ -30,9 +30,7 @@ class DB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> closeDb() async {
|
Future<void> closeDb() async {
|
||||||
if ( _db != null ) {
|
this._db.close();
|
||||||
this._db.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Database getDB() => this._db;
|
Database getDB() => this._db;
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'dart:math';
|
|
||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import 'package:aitrainer_app/bloc/timer/timer_bloc.dart';
|
||||||
|
|
||||||
final temperatureColors = [
|
final temperatureColors = [
|
||||||
const Color(0xFFB50DE2), // -20 Celsius , friggin cold
|
const Color(0xFFB50DE2), // -20 Celsius , friggin cold
|
||||||
const Color(0xFFAE0DE2),
|
const Color(0xFFAE0DE2),
|
||||||
@ -42,7 +44,7 @@ class Clock extends StatelessWidget {
|
|||||||
final TimerBloc bloc;
|
final TimerBloc bloc;
|
||||||
final List<Color> colors = temperatureColors;
|
final List<Color> colors = temperatureColors;
|
||||||
|
|
||||||
Clock({this.bloc});
|
Clock({required this.bloc});
|
||||||
|
|
||||||
// ignore: close_sinks
|
// ignore: close_sinks
|
||||||
|
|
||||||
@ -109,10 +111,10 @@ class ArcPainter extends CustomPainter {
|
|||||||
|
|
||||||
List<Color> _gradient;
|
List<Color> _gradient;
|
||||||
|
|
||||||
Offset center;
|
Offset? center;
|
||||||
double _radius;
|
double _radius;
|
||||||
|
|
||||||
Paint paintMarkerEmpty;
|
late Paint paintMarkerEmpty;
|
||||||
|
|
||||||
ArcPainter(
|
ArcPainter(
|
||||||
this._progress,
|
this._progress,
|
||||||
@ -132,7 +134,7 @@ class ArcPainter extends CustomPainter {
|
|||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
center = Offset(size.width / 2, size.height / 2);
|
center = Offset(size.width / 2, size.height / 2);
|
||||||
var rect = Rect.fromCircle(center: center, radius: this._radius);
|
var rect = Rect.fromCircle(center: center!, radius: this._radius);
|
||||||
|
|
||||||
final gradient2 = new SweepGradient(
|
final gradient2 = new SweepGradient(
|
||||||
startAngle: -pi / 2,
|
startAngle: -pi / 2,
|
||||||
|
@ -1,529 +0,0 @@
|
|||||||
library dropdown_search;
|
|
||||||
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
|
||||||
|
|
||||||
import 'popup_menu.dart';
|
|
||||||
import 'select_dialog.dart';
|
|
||||||
|
|
||||||
typedef Future<List<T>> DropdownSearchOnFind<T>(String text);
|
|
||||||
typedef String DropdownSearchItemAsString<T>(T item);
|
|
||||||
typedef bool DropdownSearchFilterFn<T>(T item, String filter);
|
|
||||||
typedef bool DropdownSearchCompareFn<T>(T item, T selectedItem);
|
|
||||||
typedef Widget DropdownSearchBuilder<T>(BuildContext context, T selectedItem, String itemAsString);
|
|
||||||
typedef Widget DropdownSearchPopupItemBuilder<T>(
|
|
||||||
BuildContext context,
|
|
||||||
T item,
|
|
||||||
bool isSelected,
|
|
||||||
);
|
|
||||||
typedef bool DropdownSearchPopupItemEnabled<T>(T item);
|
|
||||||
typedef Widget ErrorBuilder<T>(BuildContext context, String searchEntry, dynamic exception);
|
|
||||||
typedef Widget EmptyBuilder<T>(BuildContext context, String searchEntry);
|
|
||||||
typedef Widget LoadingBuilder<T>(BuildContext context, String searchEntry);
|
|
||||||
typedef Widget IconButtonBuilder(BuildContext context);
|
|
||||||
typedef Future<bool> BeforeChange<T>(T prevItem, T nextItem);
|
|
||||||
|
|
||||||
enum Mode { DIALOG, BOTTOM_SHEET, MENU }
|
|
||||||
|
|
||||||
class DropdownSearch<T> extends StatefulWidget {
|
|
||||||
///DropDownSearch label
|
|
||||||
final String label;
|
|
||||||
|
|
||||||
///DropDownSearch hint
|
|
||||||
final String hint;
|
|
||||||
|
|
||||||
///show/hide the search box
|
|
||||||
final bool showSearchBox;
|
|
||||||
|
|
||||||
///true if the filter on items is applied onlie (via API)
|
|
||||||
final bool isFilteredOnline;
|
|
||||||
|
|
||||||
///show/hide clear selected item
|
|
||||||
final bool showClearButton;
|
|
||||||
|
|
||||||
///offline items list
|
|
||||||
final List<T> items;
|
|
||||||
|
|
||||||
///selected item
|
|
||||||
final T selectedItem;
|
|
||||||
|
|
||||||
///function that returns item from API
|
|
||||||
final DropdownSearchOnFind<T> onFind;
|
|
||||||
|
|
||||||
///called when a new item is selected
|
|
||||||
final ValueChanged<T> onChanged;
|
|
||||||
|
|
||||||
///to customize list of items UI
|
|
||||||
final DropdownSearchBuilder<T> dropdownBuilder;
|
|
||||||
|
|
||||||
///to customize selected item
|
|
||||||
final DropdownSearchPopupItemBuilder<T> popupItemBuilder;
|
|
||||||
|
|
||||||
///decoration for search box
|
|
||||||
final InputDecoration searchBoxDecoration;
|
|
||||||
|
|
||||||
///the title for dialog/menu/bottomSheet
|
|
||||||
final Color popupBackgroundColor;
|
|
||||||
|
|
||||||
///custom widget for the popup title
|
|
||||||
final Widget popupTitle;
|
|
||||||
|
|
||||||
///customize the fields the be shown
|
|
||||||
final DropdownSearchItemAsString<T> itemAsString;
|
|
||||||
|
|
||||||
/// custom filter function
|
|
||||||
final DropdownSearchFilterFn<T> filterFn;
|
|
||||||
|
|
||||||
///enable/disable dropdownSearch
|
|
||||||
final bool enabled;
|
|
||||||
|
|
||||||
///MENU / DIALOG/ BOTTOM_SHEET
|
|
||||||
final Mode mode;
|
|
||||||
|
|
||||||
///the max height for dialog/bottomSheet/Menu
|
|
||||||
final double maxHeight;
|
|
||||||
|
|
||||||
///the max width for the dialog
|
|
||||||
final double dialogMaxWidth;
|
|
||||||
|
|
||||||
///select the selected item in the menu/dialog/bottomSheet of items
|
|
||||||
final bool showSelectedItem;
|
|
||||||
|
|
||||||
///function that compares two object with the same type to detected if it's the selected item or not
|
|
||||||
final DropdownSearchCompareFn<T> compareFn;
|
|
||||||
|
|
||||||
///dropdownSearch input decoration
|
|
||||||
final InputDecoration dropdownSearchDecoration;
|
|
||||||
|
|
||||||
///custom layout for empty results
|
|
||||||
final EmptyBuilder emptyBuilder;
|
|
||||||
|
|
||||||
///custom layout for loading items
|
|
||||||
final LoadingBuilder loadingBuilder;
|
|
||||||
|
|
||||||
///custom layout for error
|
|
||||||
final ErrorBuilder errorBuilder;
|
|
||||||
|
|
||||||
///the search box will be focused if true
|
|
||||||
final bool autoFocusSearchBox;
|
|
||||||
|
|
||||||
///custom shape for the popup
|
|
||||||
final ShapeBorder popupShape;
|
|
||||||
|
|
||||||
final AutovalidateMode autoValidateMode;
|
|
||||||
|
|
||||||
/// An optional method to call with the final value when the form is saved via
|
|
||||||
final FormFieldSetter<T> onSaved;
|
|
||||||
|
|
||||||
/// An optional method that validates an input. Returns an error string to
|
|
||||||
/// display if the input is invalid, or null otherwise.
|
|
||||||
final FormFieldValidator<T> validator;
|
|
||||||
|
|
||||||
///custom dropdown clear button icon widget
|
|
||||||
final Widget clearButton;
|
|
||||||
|
|
||||||
///custom clear button widget builder
|
|
||||||
final IconButtonBuilder clearButtonBuilder;
|
|
||||||
|
|
||||||
///custom dropdown icon button widget
|
|
||||||
final Widget dropDownButton;
|
|
||||||
|
|
||||||
///custom dropdown button widget builder
|
|
||||||
final IconButtonBuilder dropdownButtonBuilder;
|
|
||||||
|
|
||||||
///whether to manage the clear and dropdown icons via InputDecoration suffixIcon
|
|
||||||
final bool showAsSuffixIcons;
|
|
||||||
|
|
||||||
///If true, the dropdownBuilder will continue the uses of material behavior
|
|
||||||
///This will be useful if you want to handle a custom UI only if the item !=null
|
|
||||||
final bool dropdownBuilderSupportsNullItem;
|
|
||||||
|
|
||||||
///defines if an item of the popup is enabled or not, if the item is disabled,
|
|
||||||
///it cannot be clicked
|
|
||||||
final DropdownSearchPopupItemEnabled<T> popupItemDisabled;
|
|
||||||
|
|
||||||
///set a custom color for the popup barrier
|
|
||||||
final Color popupBarrierColor;
|
|
||||||
|
|
||||||
///text controller to set default search word for example
|
|
||||||
final TextEditingController searchBoxController;
|
|
||||||
|
|
||||||
///called when popup is dismissed
|
|
||||||
final VoidCallback onPopupDismissed;
|
|
||||||
|
|
||||||
/// callback executed before applying value change
|
|
||||||
///delay before searching, change it to Duration(milliseconds: 0)
|
|
||||||
///if you do not use online search
|
|
||||||
final Duration searchDelay;
|
|
||||||
|
|
||||||
/// callback executed before applying value change
|
|
||||||
final BeforeChange<T> onBeforeChange;
|
|
||||||
|
|
||||||
DropdownSearch({
|
|
||||||
Key key,
|
|
||||||
this.onSaved,
|
|
||||||
this.validator,
|
|
||||||
this.autoValidateMode = AutovalidateMode.disabled,
|
|
||||||
this.onChanged,
|
|
||||||
this.mode = Mode.DIALOG,
|
|
||||||
this.label,
|
|
||||||
this.hint,
|
|
||||||
this.isFilteredOnline = false,
|
|
||||||
this.popupTitle,
|
|
||||||
this.items,
|
|
||||||
this.selectedItem,
|
|
||||||
this.onFind,
|
|
||||||
this.dropdownBuilder,
|
|
||||||
this.popupItemBuilder,
|
|
||||||
this.showSearchBox = false,
|
|
||||||
this.showClearButton = false,
|
|
||||||
this.searchBoxDecoration,
|
|
||||||
this.popupBackgroundColor,
|
|
||||||
this.enabled = true,
|
|
||||||
this.maxHeight,
|
|
||||||
this.filterFn,
|
|
||||||
this.itemAsString,
|
|
||||||
this.showSelectedItem = false,
|
|
||||||
this.compareFn,
|
|
||||||
this.dropdownSearchDecoration,
|
|
||||||
this.emptyBuilder,
|
|
||||||
this.loadingBuilder,
|
|
||||||
this.errorBuilder,
|
|
||||||
this.autoFocusSearchBox = false,
|
|
||||||
this.dialogMaxWidth,
|
|
||||||
this.clearButton,
|
|
||||||
this.clearButtonBuilder,
|
|
||||||
this.dropDownButton,
|
|
||||||
this.dropdownButtonBuilder,
|
|
||||||
this.showAsSuffixIcons = false,
|
|
||||||
this.dropdownBuilderSupportsNullItem = false,
|
|
||||||
this.popupShape,
|
|
||||||
this.popupItemDisabled,
|
|
||||||
this.popupBarrierColor,
|
|
||||||
this.onPopupDismissed,
|
|
||||||
this.searchBoxController,
|
|
||||||
this.searchDelay,
|
|
||||||
this.onBeforeChange,
|
|
||||||
}) : assert(isFilteredOnline != null),
|
|
||||||
assert(dropdownBuilderSupportsNullItem != null),
|
|
||||||
assert(enabled != null),
|
|
||||||
assert(showSelectedItem != null),
|
|
||||||
assert(autoFocusSearchBox != null),
|
|
||||||
assert(showClearButton != null),
|
|
||||||
assert(showSearchBox != null),
|
|
||||||
assert(!showSelectedItem || T == String || compareFn != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
DropdownSearchState<T> createState() => DropdownSearchState<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class DropdownSearchState<T> extends State<DropdownSearch<T>> {
|
|
||||||
final ValueNotifier<T> _selectedItemNotifier = ValueNotifier(null);
|
|
||||||
final ValueNotifier<bool> _isFocused = ValueNotifier(false);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_selectedItemNotifier.value = widget.selectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didUpdateWidget(DropdownSearch<T> oldWidget) {
|
|
||||||
final oldSelectedItem = oldWidget.selectedItem;
|
|
||||||
final newSelectedItem = widget.selectedItem;
|
|
||||||
if (oldSelectedItem != newSelectedItem) {
|
|
||||||
_selectedItemNotifier.value = newSelectedItem;
|
|
||||||
}
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ValueListenableBuilder<T>(
|
|
||||||
valueListenable: _selectedItemNotifier,
|
|
||||||
builder: (context, T data, wt) {
|
|
||||||
return IgnorePointer(
|
|
||||||
ignoring: !widget.enabled,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => _selectSearchMode(data),
|
|
||||||
child: _formField(data),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _defaultSelectItemWidget(T data) {
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: widget.dropdownBuilder != null
|
|
||||||
? widget.dropdownBuilder(
|
|
||||||
context,
|
|
||||||
data,
|
|
||||||
_selectedItemAsString(data),
|
|
||||||
)
|
|
||||||
: Text(_selectedItemAsString(data), style: Theme.of(context).textTheme.subtitle1),
|
|
||||||
),
|
|
||||||
if (!widget.showAsSuffixIcons) _manageTrailingIcons(data),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _formField(T value) {
|
|
||||||
return FormField(
|
|
||||||
enabled: widget.enabled,
|
|
||||||
onSaved: widget.onSaved,
|
|
||||||
validator: widget.validator,
|
|
||||||
autovalidateMode: widget.autoValidateMode,
|
|
||||||
initialValue: widget.selectedItem,
|
|
||||||
builder: (FormFieldState<T> state) {
|
|
||||||
if (state.value != value) {
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
state.didChange(value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return ValueListenableBuilder(
|
|
||||||
valueListenable: _isFocused,
|
|
||||||
builder: (context, bool isFocused, w) {
|
|
||||||
return InputDecorator(
|
|
||||||
isEmpty: value == null && (widget.dropdownBuilder == null || widget.dropdownBuilderSupportsNullItem),
|
|
||||||
isFocused: isFocused,
|
|
||||||
decoration: _manageDropdownDecoration(state, value),
|
|
||||||
child: _defaultSelectItemWidget(value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///manage dropdownSearch field decoration
|
|
||||||
InputDecoration _manageDropdownDecoration(FormFieldState state, T data) {
|
|
||||||
return (widget.dropdownSearchDecoration ??
|
|
||||||
InputDecoration(contentPadding: EdgeInsets.fromLTRB(12, 12, 0, 0), border: OutlineInputBorder()))
|
|
||||||
.applyDefaults(Theme.of(state.context).inputDecorationTheme)
|
|
||||||
.copyWith(
|
|
||||||
enabled: widget.enabled,
|
|
||||||
labelText: widget.label,
|
|
||||||
hintText: widget.hint,
|
|
||||||
suffixIcon: widget.showAsSuffixIcons ? _manageTrailingIcons(data) : null,
|
|
||||||
errorText: state.errorText);
|
|
||||||
}
|
|
||||||
|
|
||||||
///function that return the String value of an object
|
|
||||||
String _selectedItemAsString(T data) {
|
|
||||||
if (data == null) {
|
|
||||||
return "";
|
|
||||||
} else if (widget.itemAsString != null) {
|
|
||||||
return widget.itemAsString(data);
|
|
||||||
} else {
|
|
||||||
return data.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///function that manage Trailing icons(close, dropDown)
|
|
||||||
Widget _manageTrailingIcons(T data) {
|
|
||||||
final clearButtonPressed = () => _handleOnChangeSelectedItem(null);
|
|
||||||
final dropdownButtonPressed = () => _selectSearchMode(data);
|
|
||||||
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: <Widget>[
|
|
||||||
if (data != null && widget.showClearButton)
|
|
||||||
widget.clearButtonBuilder != null
|
|
||||||
? GestureDetector(
|
|
||||||
onTap: clearButtonPressed,
|
|
||||||
child: widget.clearButtonBuilder(context),
|
|
||||||
)
|
|
||||||
: IconButton(
|
|
||||||
icon: widget.clearButton ?? const Icon(Icons.clear, size: 24),
|
|
||||||
onPressed: clearButtonPressed,
|
|
||||||
),
|
|
||||||
widget.dropdownButtonBuilder != null
|
|
||||||
? GestureDetector(
|
|
||||||
onTap: dropdownButtonPressed,
|
|
||||||
child: widget.dropdownButtonBuilder(context),
|
|
||||||
)
|
|
||||||
: IconButton(
|
|
||||||
icon: widget.dropDownButton ?? const Icon(Icons.arrow_drop_down, size: 24),
|
|
||||||
onPressed: dropdownButtonPressed,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///open dialog
|
|
||||||
Future<T> _openSelectDialog(T data) {
|
|
||||||
return showGeneralDialog(
|
|
||||||
barrierDismissible: true,
|
|
||||||
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
|
||||||
transitionDuration: const Duration(milliseconds: 400),
|
|
||||||
barrierColor: widget.popupBarrierColor ?? const Color(0x80000000),
|
|
||||||
context: context,
|
|
||||||
pageBuilder: (context, animation, secondaryAnimation) {
|
|
||||||
return AlertDialog(
|
|
||||||
contentPadding: EdgeInsets.all(0),
|
|
||||||
shape: widget.popupShape,
|
|
||||||
backgroundColor: widget.popupBackgroundColor,
|
|
||||||
content: _selectDialogInstance(data),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///open BottomSheet (Dialog mode)
|
|
||||||
Future<T> _openBottomSheet(T data) {
|
|
||||||
return showModalBottomSheet<T>(
|
|
||||||
barrierColor: widget.popupBarrierColor,
|
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: widget.popupBackgroundColor,
|
|
||||||
shape: widget.popupShape,
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return AnimatedPadding(
|
|
||||||
duration: Duration(milliseconds: 300),
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
bottom: MediaQuery.of(context).viewInsets.bottom,
|
|
||||||
),
|
|
||||||
child: _selectDialogInstance(data, defaultHeight: 350),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
///openMenu
|
|
||||||
Future<T> _openMenu(T data) {
|
|
||||||
// Here we get the render object of our physical button, later to get its size & position
|
|
||||||
final RenderBox popupButtonObject = context.findRenderObject();
|
|
||||||
// Get the render object of the overlay used in `Navigator` / `MaterialApp`, i.e. screen size reference
|
|
||||||
final RenderBox overlay = Overlay.of(context).context.findRenderObject();
|
|
||||||
// Calculate the show-up area for the dropdown using button's size & position based on the `overlay` used as the coordinate space.
|
|
||||||
final RelativeRect position = RelativeRect.fromSize(
|
|
||||||
Rect.fromPoints(
|
|
||||||
popupButtonObject.localToGlobal(popupButtonObject.size.bottomLeft(Offset.zero), ancestor: overlay),
|
|
||||||
popupButtonObject.localToGlobal(popupButtonObject.size.bottomRight(Offset.zero), ancestor: overlay),
|
|
||||||
),
|
|
||||||
Size(overlay.size.width, overlay.size.height),
|
|
||||||
);
|
|
||||||
return customShowMenu<T>(
|
|
||||||
barrierColor: widget.popupBarrierColor,
|
|
||||||
shape: widget.popupShape,
|
|
||||||
color: widget.popupBackgroundColor,
|
|
||||||
context: context,
|
|
||||||
position: position,
|
|
||||||
elevation: 8,
|
|
||||||
items: [
|
|
||||||
CustomPopupMenuItem(
|
|
||||||
enabled: false,
|
|
||||||
child: Container(
|
|
||||||
width: popupButtonObject.size.width,
|
|
||||||
child: _selectDialogInstance(data, defaultHeight: 224),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectDialog<T> _selectDialogInstance(T data, {double defaultHeight}) {
|
|
||||||
return SelectDialog<T>(
|
|
||||||
popupTitle: widget.popupTitle,
|
|
||||||
maxHeight: widget.maxHeight ?? defaultHeight,
|
|
||||||
isFilteredOnline: widget.isFilteredOnline,
|
|
||||||
itemAsString: widget.itemAsString,
|
|
||||||
filterFn: widget.filterFn,
|
|
||||||
items: widget.items,
|
|
||||||
onFind: widget.onFind,
|
|
||||||
showSearchBox: widget.showSearchBox,
|
|
||||||
itemBuilder: widget.popupItemBuilder,
|
|
||||||
selectedValue: data,
|
|
||||||
searchBoxDecoration: widget.searchBoxDecoration,
|
|
||||||
onChanged: _handleOnChangeSelectedItem,
|
|
||||||
showSelectedItem: widget.showSelectedItem,
|
|
||||||
compareFn: widget.compareFn,
|
|
||||||
emptyBuilder: widget.emptyBuilder,
|
|
||||||
loadingBuilder: widget.loadingBuilder,
|
|
||||||
errorBuilder: widget.errorBuilder,
|
|
||||||
autoFocusSearchBox: widget.autoFocusSearchBox,
|
|
||||||
dialogMaxWidth: widget.dialogMaxWidth,
|
|
||||||
itemDisabled: widget.popupItemDisabled,
|
|
||||||
searchBoxController: widget.searchBoxController ?? TextEditingController(),
|
|
||||||
searchDelay: widget.searchDelay,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///Function that manage focus listener
|
|
||||||
///set true only if the widget already not focused to prevent unnecessary build
|
|
||||||
///same thing for clear focus,
|
|
||||||
void _handleFocus(bool isFocused) {
|
|
||||||
if (isFocused && !_isFocused.value) {
|
|
||||||
FocusScope.of(context).unfocus();
|
|
||||||
_isFocused.value = true;
|
|
||||||
} else if (!isFocused && _isFocused.value) _isFocused.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
///handle on change value , if the validation is active , we validate the new selected item
|
|
||||||
void _handleOnChangeSelectedItem(T selectedItem) {
|
|
||||||
final changeItem = () {
|
|
||||||
_selectedItemNotifier.value = selectedItem;
|
|
||||||
if (widget.onChanged != null) widget.onChanged(selectedItem);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (widget.onBeforeChange != null) {
|
|
||||||
widget.onBeforeChange(_selectedItemNotifier.value, selectedItem).then((value) {
|
|
||||||
if (value == true) {
|
|
||||||
changeItem();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
changeItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
_handleFocus(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
///Function that return then UI based on searchMode
|
|
||||||
///[data] selected item to be passed to the UI
|
|
||||||
///If we close the popup , or maybe we just selected
|
|
||||||
///another widget we should clear the focus
|
|
||||||
Future<T> _selectSearchMode(T data) async {
|
|
||||||
_handleFocus(true);
|
|
||||||
T selectedItem;
|
|
||||||
if (widget.mode == Mode.MENU) {
|
|
||||||
selectedItem = await _openMenu(data);
|
|
||||||
} else if (widget.mode == Mode.BOTTOM_SHEET) {
|
|
||||||
selectedItem = await _openBottomSheet(data);
|
|
||||||
} else {
|
|
||||||
selectedItem = await _openSelectDialog(data);
|
|
||||||
}
|
|
||||||
_handleFocus(false);
|
|
||||||
widget.onPopupDismissed?.call();
|
|
||||||
|
|
||||||
return selectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
///Public Function that return then UI based on searchMode
|
|
||||||
///[data] selected item to be passed to the UI
|
|
||||||
///If we close the popup , or maybe we just selected
|
|
||||||
///another widget we should clear the focus
|
|
||||||
///THIS USED FOR OPEN DROPDOWN_SEARCH PROGRAMMATICALLY,
|
|
||||||
///otherwise you can you [_selectSearchMode]
|
|
||||||
Future<T> openDropDownSearch() => _selectSearchMode(_selectedItemNotifier.value);
|
|
||||||
|
|
||||||
///Change selected Value; this function is public USED to change the selected
|
|
||||||
///value PROGRAMMATICALLY, Otherwise you can use [_handleOnChangeSelectedItem]
|
|
||||||
void changeSelectedItem(T selectedItem) => _handleOnChangeSelectedItem(selectedItem);
|
|
||||||
|
|
||||||
///Change selected Value; this function is public USED to clear selected
|
|
||||||
///value PROGRAMMATICALLY, Otherwise you can use [_handleOnChangeSelectedItem]
|
|
||||||
void clear() => _handleOnChangeSelectedItem(null);
|
|
||||||
|
|
||||||
///get selected value programmatically
|
|
||||||
T get getSelectedItem => _selectedItemNotifier.value;
|
|
||||||
|
|
||||||
///check if the dropdownSearch is focused
|
|
||||||
bool get isFocused => _isFocused.value;
|
|
||||||
}
|
|
@ -16,9 +16,9 @@ class FadeIn extends StatefulWidget {
|
|||||||
final Curve curve;
|
final Curve curve;
|
||||||
|
|
||||||
const FadeIn({
|
const FadeIn({
|
||||||
Key key,
|
Key? key,
|
||||||
this.controller,
|
required this.controller,
|
||||||
this.child,
|
required this.child,
|
||||||
this.duration = const Duration(milliseconds: 250),
|
this.duration = const Duration(milliseconds: 250),
|
||||||
this.curve = Curves.easeIn,
|
this.curve = Curves.easeIn,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -57,8 +57,8 @@ class FadeInController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
||||||
AnimationController _controller;
|
late AnimationController _controller;
|
||||||
StreamSubscription<FadeInAction> _listener;
|
late StreamSubscription<FadeInAction> _listener;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -71,11 +71,11 @@ class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
_setupCurve();
|
_setupCurve();
|
||||||
|
|
||||||
if (widget.controller?.autoStart != false) {
|
if (widget.controller.autoStart != false) {
|
||||||
fadeIn();
|
fadeIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
_listen();
|
_listener = widget.controller.stream.listen(_onAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setupCurve() {
|
void _setupCurve() {
|
||||||
@ -87,17 +87,6 @@ class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
|||||||
).animate(curve);
|
).animate(curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _listen() {
|
|
||||||
if (_listener != null) {
|
|
||||||
_listener.cancel();
|
|
||||||
_listener = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (widget.controller != null) {
|
|
||||||
_listener = widget.controller.stream.listen(_onAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onAction(FadeInAction action) {
|
void _onAction(FadeInAction action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case FadeInAction.fadeIn:
|
case FadeInAction.fadeIn:
|
||||||
@ -112,7 +101,7 @@ class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(FadeIn oldWidget) {
|
void didUpdateWidget(FadeIn oldWidget) {
|
||||||
if (oldWidget.controller != widget.controller) {
|
if (oldWidget.controller != widget.controller) {
|
||||||
_listen();
|
_listener = widget.controller.stream.listen(_onAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldWidget.duration != widget.duration) {
|
if (oldWidget.duration != widget.duration) {
|
||||||
@ -129,6 +118,7 @@ class _FadeInState extends State<FadeIn> with TickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
|
_listener.cancel();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
lib/library/flurry.dart
Normal file
39
lib/library/flurry.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class Flurry {
|
||||||
|
static const MethodChannel _channel = const MethodChannel('flurry');
|
||||||
|
|
||||||
|
static Future<String> get platformVersion async {
|
||||||
|
final String version = await _channel.invokeMethod('getPlatformVersion');
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Null> initialize({String androidKey = "", String iosKey = "", bool enableLog = true}) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("api_key_android", () => androidKey);
|
||||||
|
args.putIfAbsent("api_key_ios", () => iosKey);
|
||||||
|
args.putIfAbsent("is_log_enabled", () => enableLog);
|
||||||
|
|
||||||
|
await _channel.invokeMethod('initialize', args);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Null> logEvent(String message) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("message", () => message);
|
||||||
|
|
||||||
|
await _channel.invokeMethod('logEvent', args);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<Null> setUserId(String userId) async {
|
||||||
|
Map<String, dynamic> args = <String, dynamic>{};
|
||||||
|
args.putIfAbsent("userId", () => userId);
|
||||||
|
|
||||||
|
await _channel.invokeMethod('userId', args);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -119,21 +119,17 @@ class GradientBottomNavigationBar extends StatefulWidget {
|
|||||||
/// [ThemeData.primaryColor], is used. However if [GradientBottomNavigationBar.type] is
|
/// [ThemeData.primaryColor], is used. However if [GradientBottomNavigationBar.type] is
|
||||||
/// [BottomNavigationBarType.shifting] then [fixedColor] is ignored.
|
/// [BottomNavigationBarType.shifting] then [fixedColor] is ignored.
|
||||||
GradientBottomNavigationBar({
|
GradientBottomNavigationBar({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.items,
|
required this.items,
|
||||||
this.onTap,
|
required this.onTap,
|
||||||
@required this.backgroundColorStart,
|
required this.backgroundColorStart,
|
||||||
@required this.backgroundColorEnd,
|
required this.backgroundColorEnd,
|
||||||
this.currentIndex = 0,
|
this.currentIndex = 0,
|
||||||
BottomNavigationBarType type,
|
BottomNavigationBarType? type,
|
||||||
this.fixedColor,
|
this.fixedColor = Colors.white,
|
||||||
this.iconSize = 24.0,
|
this.iconSize = 24.0,
|
||||||
}) : assert(items != null),
|
}) : assert(items.length >= 2),
|
||||||
assert(items.length >= 2),
|
|
||||||
assert(backgroundColorStart != null),
|
|
||||||
assert(backgroundColorEnd != null),
|
|
||||||
assert(0 <= currentIndex && currentIndex < items.length),
|
assert(0 <= currentIndex && currentIndex < items.length),
|
||||||
assert(iconSize != null),
|
|
||||||
type = type ?? (items.length <= 3 ? BottomNavigationBarType.fixed : BottomNavigationBarType.shifting),
|
type = type ?? (items.length <= 3 ? BottomNavigationBarType.fixed : BottomNavigationBarType.shifting),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
@ -188,30 +184,30 @@ class _BottomNavigationTile extends StatelessWidget {
|
|||||||
this.item,
|
this.item,
|
||||||
this.animation,
|
this.animation,
|
||||||
this.iconSize, {
|
this.iconSize, {
|
||||||
this.onTap,
|
required this.onTap,
|
||||||
this.colorTween,
|
this.colorTween,
|
||||||
this.flex,
|
this.flex,
|
||||||
this.selected = false,
|
this.selected = false,
|
||||||
this.indexLabel,
|
required this.indexLabel,
|
||||||
}) : assert(selected != null);
|
});
|
||||||
|
|
||||||
final BottomNavigationBarType type;
|
final BottomNavigationBarType type;
|
||||||
final BottomNavigationBarItem item;
|
final BottomNavigationBarItem item;
|
||||||
final Animation<double> animation;
|
final Animation<double> animation;
|
||||||
final double iconSize;
|
final double iconSize;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
final ColorTween colorTween;
|
final ColorTween? colorTween;
|
||||||
final double flex;
|
final double? flex;
|
||||||
final bool selected;
|
final bool selected;
|
||||||
final String indexLabel;
|
final String indexLabel;
|
||||||
|
|
||||||
Widget _buildIcon() {
|
Widget _buildIcon() {
|
||||||
double tweenStart;
|
double tweenStart;
|
||||||
Color iconColor;
|
Color? iconColor;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BottomNavigationBarType.fixed:
|
case BottomNavigationBarType.fixed:
|
||||||
tweenStart = 8.0;
|
tweenStart = 8.0;
|
||||||
iconColor = colorTween.evaluate(animation);
|
iconColor = colorTween!.evaluate(animation);
|
||||||
break;
|
break;
|
||||||
case BottomNavigationBarType.shifting:
|
case BottomNavigationBarType.shifting:
|
||||||
tweenStart = 16.0;
|
tweenStart = 16.0;
|
||||||
@ -248,7 +244,7 @@ class _BottomNavigationTile extends StatelessWidget {
|
|||||||
child: DefaultTextStyle.merge(
|
child: DefaultTextStyle.merge(
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: _kActiveFontSize,
|
fontSize: _kActiveFontSize,
|
||||||
color: colorTween.evaluate(animation),
|
color: colorTween!.evaluate(animation),
|
||||||
),
|
),
|
||||||
// The font size should grow here when active, but because of the way
|
// The font size should grow here when active, but because of the way
|
||||||
// font rendering works, it doesn't grow smoothly if we just animate
|
// font rendering works, it doesn't grow smoothly if we just animate
|
||||||
@ -293,7 +289,7 @@ class _BottomNavigationTile extends StatelessWidget {
|
|||||||
fontSize: _kActiveFontSize,
|
fontSize: _kActiveFontSize,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
child: item.title,
|
child: item.title!,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -314,7 +310,7 @@ class _BottomNavigationTile extends StatelessWidget {
|
|||||||
label = _buildFixedLabel();
|
label = _buildFixedLabel();
|
||||||
break;
|
break;
|
||||||
case BottomNavigationBarType.shifting:
|
case BottomNavigationBarType.shifting:
|
||||||
size = (flex * 1000.0).round();
|
size = (flex! * 1000.0).round();
|
||||||
label = _buildShiftingLabel();
|
label = _buildShiftingLabel();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -350,14 +346,14 @@ class _BottomNavigationTile extends StatelessWidget {
|
|||||||
|
|
||||||
class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBar> with TickerProviderStateMixin {
|
class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBar> with TickerProviderStateMixin {
|
||||||
List<AnimationController> _controllers = <AnimationController>[];
|
List<AnimationController> _controllers = <AnimationController>[];
|
||||||
List<CurvedAnimation> _animations;
|
late List<CurvedAnimation> _animations;
|
||||||
|
|
||||||
// A queue of color splashes currently being animated.
|
// A queue of color splashes currently being animated.
|
||||||
final Queue<_Circle> _circles = Queue<_Circle>();
|
final Queue<_Circle> _circles = Queue<_Circle>();
|
||||||
|
|
||||||
// Last splash circle's color, and the final color of the control after
|
// Last splash circle's color, and the final color of the control after
|
||||||
// animation is complete.
|
// animation is complete.
|
||||||
Color _backgroundColor;
|
late Color _backgroundColor;
|
||||||
|
|
||||||
static final Animatable<double> _flexTween = Tween<double>(begin: 1.0, end: 1.5);
|
static final Animatable<double> _flexTween = Tween<double>(begin: 1.0, end: 1.5);
|
||||||
|
|
||||||
@ -380,7 +376,7 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
_controllers[widget.currentIndex].value = 1.0;
|
_controllers[widget.currentIndex].value = 1.0;
|
||||||
_backgroundColor = widget.items[widget.currentIndex].backgroundColor;
|
_backgroundColor = widget.items[widget.currentIndex].backgroundColor!;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -411,7 +407,7 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
_Circle(
|
_Circle(
|
||||||
state: this,
|
state: this,
|
||||||
index: index,
|
index: index,
|
||||||
color: widget.items[index].backgroundColor,
|
color: widget.items[index].backgroundColor!,
|
||||||
vsync: this,
|
vsync: this,
|
||||||
)..controller.addStatusListener(
|
)..controller.addStatusListener(
|
||||||
(AnimationStatus status) {
|
(AnimationStatus status) {
|
||||||
@ -456,30 +452,22 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
_controllers[widget.currentIndex].forward();
|
_controllers[widget.currentIndex].forward();
|
||||||
} else {
|
} else {
|
||||||
if (_backgroundColor != widget.items[widget.currentIndex].backgroundColor)
|
if (_backgroundColor != widget.items[widget.currentIndex].backgroundColor)
|
||||||
_backgroundColor = widget.items[widget.currentIndex].backgroundColor;
|
_backgroundColor = widget.items[widget.currentIndex].backgroundColor!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _createTiles() {
|
List<Widget> _createTiles() {
|
||||||
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
|
||||||
assert(localizations != null);
|
|
||||||
final List<Widget> children = <Widget>[];
|
final List<Widget> children = <Widget>[];
|
||||||
switch (widget.type) {
|
switch (widget.type) {
|
||||||
case BottomNavigationBarType.fixed:
|
case BottomNavigationBarType.fixed:
|
||||||
final ThemeData themeData = Theme.of(context);
|
final ThemeData themeData = Theme.of(context);
|
||||||
final TextTheme textTheme = themeData.textTheme;
|
final TextTheme textTheme = themeData.textTheme;
|
||||||
Color themeColor;
|
|
||||||
switch (themeData.brightness) {
|
|
||||||
case Brightness.light:
|
|
||||||
themeColor = themeData.primaryColor;
|
|
||||||
break;
|
|
||||||
case Brightness.dark:
|
|
||||||
themeColor = themeData.accentColor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final ColorTween colorTween = ColorTween(
|
final ColorTween colorTween = ColorTween(
|
||||||
begin: textTheme.caption.color,
|
begin: textTheme.caption!.color,
|
||||||
end: widget.fixedColor ?? themeColor,
|
end: widget.fixedColor,
|
||||||
);
|
);
|
||||||
for (int i = 0; i < widget.items.length; i += 1) {
|
for (int i = 0; i < widget.items.length; i += 1) {
|
||||||
children.add(
|
children.add(
|
||||||
@ -488,9 +476,7 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
widget.items[i],
|
widget.items[i],
|
||||||
_animations[i],
|
_animations[i],
|
||||||
widget.iconSize,
|
widget.iconSize,
|
||||||
onTap: () {
|
onTap: () => widget.onTap(i),
|
||||||
if (widget.onTap != null) widget.onTap(i);
|
|
||||||
},
|
|
||||||
colorTween: colorTween,
|
colorTween: colorTween,
|
||||||
selected: i == widget.currentIndex,
|
selected: i == widget.currentIndex,
|
||||||
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
|
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
|
||||||
@ -506,9 +492,7 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
widget.items[i],
|
widget.items[i],
|
||||||
_animations[i],
|
_animations[i],
|
||||||
widget.iconSize,
|
widget.iconSize,
|
||||||
onTap: () {
|
onTap: () => widget.onTap(i),
|
||||||
if (widget.onTap != null) widget.onTap(i);
|
|
||||||
},
|
|
||||||
flex: _evaluateFlex(_animations[i]),
|
flex: _evaluateFlex(_animations[i]),
|
||||||
selected: i == widget.currentIndex,
|
selected: i == widget.currentIndex,
|
||||||
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
|
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
|
||||||
@ -599,13 +583,11 @@ class _GradientBottomNavigationBarState extends State<GradientBottomNavigationBa
|
|||||||
// Describes an animating color splash circle.
|
// Describes an animating color splash circle.
|
||||||
class _Circle {
|
class _Circle {
|
||||||
_Circle({
|
_Circle({
|
||||||
@required this.state,
|
required this.state,
|
||||||
@required this.index,
|
required this.index,
|
||||||
@required this.color,
|
required this.color,
|
||||||
@required TickerProvider vsync,
|
required TickerProvider vsync,
|
||||||
}) : assert(state != null),
|
}) {
|
||||||
assert(index != null),
|
|
||||||
assert(color != null) {
|
|
||||||
controller = AnimationController(
|
controller = AnimationController(
|
||||||
duration: kThemeAnimationDuration,
|
duration: kThemeAnimationDuration,
|
||||||
vsync: vsync,
|
vsync: vsync,
|
||||||
@ -620,8 +602,8 @@ class _Circle {
|
|||||||
final _GradientBottomNavigationBarState state;
|
final _GradientBottomNavigationBarState state;
|
||||||
final int index;
|
final int index;
|
||||||
final Color color;
|
final Color color;
|
||||||
AnimationController controller;
|
late AnimationController controller;
|
||||||
CurvedAnimation animation;
|
late CurvedAnimation animation;
|
||||||
|
|
||||||
double get horizontalLeadingOffset {
|
double get horizontalLeadingOffset {
|
||||||
double weightSum(Iterable<Animation<double>> animations) {
|
double weightSum(Iterable<Animation<double>> animations) {
|
||||||
@ -646,10 +628,9 @@ class _Circle {
|
|||||||
// Paints the animating color splash circles.
|
// Paints the animating color splash circles.
|
||||||
class _RadialPainter extends CustomPainter {
|
class _RadialPainter extends CustomPainter {
|
||||||
_RadialPainter({
|
_RadialPainter({
|
||||||
@required this.circles,
|
required this.circles,
|
||||||
@required this.textDirection,
|
required this.textDirection,
|
||||||
}) : assert(circles != null),
|
});
|
||||||
assert(textDirection != null);
|
|
||||||
|
|
||||||
final List<_Circle> circles;
|
final List<_Circle> circles;
|
||||||
final TextDirection textDirection;
|
final TextDirection textDirection;
|
||||||
|
@ -4,7 +4,7 @@ import 'package:aitrainer_app/service/logging.dart';
|
|||||||
import 'package:aitrainer_app/util/not_found_exception.dart';
|
import 'package:aitrainer_app/util/not_found_exception.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:network_image_to_byte/network_image_to_byte.dart';
|
import 'package:aitrainer_app/library//network_image_to_byte.dart';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
class ImageCache with Logging {
|
class ImageCache with Logging {
|
||||||
@ -31,7 +31,7 @@ class ImageCache with Logging {
|
|||||||
return _imageMap[imageKey] != null && _imageMap[imageKey] == true;
|
return _imageMap[imageKey] != null && _imageMap[imageKey] == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getImageString(int id, String url) {
|
String? getImageString(int id, String url) {
|
||||||
final String imageKey = generateMd5(url + "_" + id.toString());
|
final String imageKey = generateMd5(url + "_" + id.toString());
|
||||||
return _images[imageKey];
|
return _images[imageKey];
|
||||||
}
|
}
|
||||||
@ -40,11 +40,10 @@ class ImageCache with Logging {
|
|||||||
final String imageKey = generateMd5(url + "_" + id.toString());
|
final String imageKey = generateMd5(url + "_" + id.toString());
|
||||||
|
|
||||||
// get from storage
|
// get from storage
|
||||||
final String imageString = await getImageAs64BaseString(id, url);
|
final String imageString = (await getImageAs64BaseString(id, url))!;
|
||||||
if (imageString != null) {
|
|
||||||
_images[imageKey] = imageString;
|
_images[imageKey] = imageString;
|
||||||
_imageMap[imageKey] = true;
|
_imageMap[imageKey] = true;
|
||||||
}
|
|
||||||
|
|
||||||
/* final String imageString = await getImageAs64BaseString(id, url);
|
/* final String imageString = await getImageAs64BaseString(id, url);
|
||||||
if (imageString != null) {
|
if (imageString != null) {
|
||||||
@ -67,8 +66,8 @@ class ImageCache with Logging {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> loadImageFromPrefs(String key) async {
|
Future<String?> loadImageFromPrefs(String key) async {
|
||||||
String value = await storage.read(key: key);
|
String? value = await storage.read(key: key);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,47 +82,40 @@ class ImageCache with Logging {
|
|||||||
|
|
||||||
// decode bytes from a string
|
// decode bytes from a string
|
||||||
Image imageFrom64BaseString(String base64String) {
|
Image imageFrom64BaseString(String base64String) {
|
||||||
if (base64String == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return Image.memory(
|
return Image.memory(
|
||||||
base64Decode(base64String),
|
base64Decode(base64String),
|
||||||
fit: BoxFit.fill,
|
fit: BoxFit.fill,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Image> getImage(int id, String name) async {
|
Future<Image?> getImage(int id, String name) async {
|
||||||
if (storage == null) {
|
if (name.length == 0) {
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == null || name.length == 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String imageKey = generateMd5(name + "_" + id.toString());
|
final String imageKey = generateMd5(name + "_" + id.toString());
|
||||||
final String imageString = await storage.read(key: imageKey);
|
final String? imageString = await storage.read(key: imageKey);
|
||||||
|
if (imageString == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final Image image = imageFrom64BaseString(imageString);
|
final Image image = imageFrom64BaseString(imageString);
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getImageAs64BaseString(int id, String name) async {
|
Future<String?> getImageAs64BaseString(int id, String name) async {
|
||||||
if (name == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final String imageKey = generateMd5(name + "_" + id.toString());
|
final String imageKey = generateMd5(name + "_" + id.toString());
|
||||||
String imageString;
|
String? imageString;
|
||||||
if (await storage.containsKey(key: imageKey)) {
|
if (await storage.containsKey(key: imageKey)) {
|
||||||
//log(" .. get from storage");
|
//log(" .. get from storage");
|
||||||
imageString = await storage.read(key: imageKey);
|
imageString = await storage.read(key: imageKey);
|
||||||
} else {
|
} else {
|
||||||
imageString = await downloadAndSaveImage(id, name);
|
imageString = (await downloadAndSaveImage(id, name))!;
|
||||||
//log(" .. downloaded");
|
//log(" .. downloaded");
|
||||||
}
|
}
|
||||||
return imageString;
|
return imageString;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> downloadAndSaveImage(int id, String url) async {
|
Future<String?> downloadAndSaveImage(int id, String url) async {
|
||||||
final String imageKey = generateMd5(url + "_" + id.toString());
|
final String imageKey = generateMd5(url + "_" + id.toString());
|
||||||
if (!await existImageInPrefs(imageKey)) {
|
if (!await existImageInPrefs(imageKey)) {
|
||||||
try {
|
try {
|
||||||
@ -143,12 +135,7 @@ class ImageCache with Logging {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//log(" .. from storage");
|
//log(" .. from storage");
|
||||||
final String storageString = await storage.read(key: imageKey);
|
//await storage.read(key: imageKey);
|
||||||
if (storageString != null) {
|
|
||||||
//log(" .. storage String: " + storageString);
|
|
||||||
} else {
|
|
||||||
// log(" .. storage String is NULL");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
14
lib/library/network_image_to_byte.dart
Normal file
14
lib/library/network_image_to_byte.dart
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
library network_image_to_byte;
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
Future<Uint8List> networkImageToByte(String path) async {
|
||||||
|
HttpClient httpClient = HttpClient();
|
||||||
|
var request = await httpClient.getUrl(Uri.parse(path));
|
||||||
|
var response = await request.close();
|
||||||
|
Uint8List bytes = await consolidateHttpClientResponseBytes(response);
|
||||||
|
return bytes;
|
||||||
|
}
|
@ -1,599 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/rendering.dart';
|
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
|
|
||||||
const Duration _kMenuDuration = Duration(milliseconds: 300);
|
|
||||||
const double _kMenuCloseIntervalEnd = 2.0 / 3.0;
|
|
||||||
const double _kMenuHorizontalPadding = 0.0;
|
|
||||||
const double _kMenuMinWidth = 2.0 * _kMenuWidthStep;
|
|
||||||
const double _kMenuVerticalPadding = 0.0;
|
|
||||||
const double _kMenuWidthStep = 1.0;
|
|
||||||
const double _kMenuScreenPadding = 0.0;
|
|
||||||
|
|
||||||
// This widget only exists to enable _PopupMenuRoute to save the sizes of
|
|
||||||
// each menu item. The sizes are used by _PopupMenuRouteLayout to compute the
|
|
||||||
// y coordinate of the menu's origin so that the center of selected menu
|
|
||||||
// item lines up with the center of its PopupMenuButton.
|
|
||||||
class _MenuItem extends SingleChildRenderObjectWidget {
|
|
||||||
const _MenuItem({
|
|
||||||
Key key,
|
|
||||||
@required this.onLayout,
|
|
||||||
Widget child,
|
|
||||||
}) : assert(onLayout != null),
|
|
||||||
super(key: key, child: child);
|
|
||||||
|
|
||||||
final ValueChanged<Size> onLayout;
|
|
||||||
|
|
||||||
@override
|
|
||||||
RenderObject createRenderObject(BuildContext context) {
|
|
||||||
return _RenderMenuItem(onLayout);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void updateRenderObject(BuildContext context, covariant _RenderMenuItem renderObject) {
|
|
||||||
renderObject.onLayout = onLayout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RenderMenuItem extends RenderShiftedBox {
|
|
||||||
_RenderMenuItem(this.onLayout, [RenderBox child])
|
|
||||||
: assert(onLayout != null),
|
|
||||||
super(child);
|
|
||||||
|
|
||||||
ValueChanged<Size> onLayout;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void performLayout() {
|
|
||||||
if (child == null) {
|
|
||||||
size = Size.zero;
|
|
||||||
} else {
|
|
||||||
child.layout(constraints, parentUsesSize: true);
|
|
||||||
size = constraints.constrain(child.size);
|
|
||||||
}
|
|
||||||
final BoxParentData childParentData = child.parentData;
|
|
||||||
childParentData.offset = Offset.zero;
|
|
||||||
onLayout(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An item in a material design popup menu.
|
|
||||||
///
|
|
||||||
/// To show a popup menu, use the [customShowMenu] function. To create a button that
|
|
||||||
/// shows a popup menu, consider using [PopupMenuButton].
|
|
||||||
///
|
|
||||||
/// To show a checkmark next to a popup menu item, consider using
|
|
||||||
/// [CheckedPopupMenuItem].
|
|
||||||
///
|
|
||||||
/// Typically the [child] of a [CustomPopupMenuItem] is a [Text] widget. More
|
|
||||||
/// elaborate menus with icons can use a [ListTile]. By default, a
|
|
||||||
/// [CustomPopupMenuItem] is kMinInteractiveDimension pixels high. If you use a widget
|
|
||||||
/// with a different height, it must be specified in the [height] property.
|
|
||||||
///
|
|
||||||
/// {@tool sample}
|
|
||||||
///
|
|
||||||
/// Here, a [Text] widget is used with a popup menu item. The `WhyFarther` type
|
|
||||||
/// is an enum, not shown here.
|
|
||||||
///
|
|
||||||
/// ```dart
|
|
||||||
/// const CustomPopupMenuItem<WhyFarther>(
|
|
||||||
/// value: WhyFarther.harder,
|
|
||||||
/// child: Text('Working a lot harder'),
|
|
||||||
/// )
|
|
||||||
/// ```
|
|
||||||
/// {@end-tool}
|
|
||||||
///
|
|
||||||
/// See the example at [PopupMenuButton] for how this example could be used in a
|
|
||||||
/// complete menu, and see the example at [CheckedPopupMenuItem] for one way to
|
|
||||||
/// keep the text of [CustomPopupMenuItem]s that use [Text] widgets in their [child]
|
|
||||||
/// slot aligned with the text of [CheckedPopupMenuItem]s or of [CustomPopupMenuItem]
|
|
||||||
/// that use a [ListTile] in their [child] slot.
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [PopupMenuDivider], which can be used to divide items from each other.
|
|
||||||
/// * [CheckedPopupMenuItem], a variant of [CustomPopupMenuItem] with a checkmark.
|
|
||||||
/// * [customShowMenu], a method to dynamically show a popup menu at a given location.
|
|
||||||
/// * [PopupMenuButton], an [IconButton] that automatically shows a menu when
|
|
||||||
/// it is tapped.
|
|
||||||
class CustomPopupMenuItem<T> extends PopupMenuEntry<T> {
|
|
||||||
/// Creates an item for a popup menu.
|
|
||||||
///
|
|
||||||
/// By default, the item is [enabled].
|
|
||||||
///
|
|
||||||
/// The `enabled` and `height` arguments must not be null.
|
|
||||||
const CustomPopupMenuItem({
|
|
||||||
Key key,
|
|
||||||
this.value,
|
|
||||||
this.enabled = true,
|
|
||||||
this.height = kMinInteractiveDimension,
|
|
||||||
this.textStyle,
|
|
||||||
@required this.child,
|
|
||||||
}) : assert(enabled != null),
|
|
||||||
assert(height != null),
|
|
||||||
super(key: key);
|
|
||||||
|
|
||||||
/// The value that will be returned by [customShowMenu] if this entry is selected.
|
|
||||||
final T value;
|
|
||||||
|
|
||||||
/// Whether the user is permitted to select this item.
|
|
||||||
///
|
|
||||||
/// Defaults to true. If this is false, then the item will not react to
|
|
||||||
/// touches.
|
|
||||||
final bool enabled;
|
|
||||||
|
|
||||||
/// The minimum height height of the menu item.
|
|
||||||
///
|
|
||||||
/// Defaults to [kMinInteractiveDimension] pixels.
|
|
||||||
@override
|
|
||||||
final double height;
|
|
||||||
|
|
||||||
/// The text style of the popup menu item.
|
|
||||||
///
|
|
||||||
/// If this property is null, then [PopupMenuThemeData.textStyle] is used.
|
|
||||||
/// If [PopupMenuThemeData.textStyle] is also null, then [ThemeData.textTheme.subhead] is used.
|
|
||||||
final TextStyle textStyle;
|
|
||||||
|
|
||||||
/// The widget below this widget in the tree.
|
|
||||||
///
|
|
||||||
/// Typically a single-line [ListTile] (for menus with icons) or a [Text]. An
|
|
||||||
/// appropriate [DefaultTextStyle] is put in scope for the child. In either
|
|
||||||
/// case, the text should be short enough that it won't wrap.
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool represents(T value) => value == this.value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
PopupMenuItemState<T, CustomPopupMenuItem<T>> createState() => PopupMenuItemState<T, CustomPopupMenuItem<T>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The [State] for [CustomPopupMenuItem] subclasses.
|
|
||||||
///
|
|
||||||
/// By default this implements the basic styling and layout of Material Design
|
|
||||||
/// popup menu items.
|
|
||||||
///
|
|
||||||
/// The [buildChild] method can be overridden to adjust exactly what gets placed
|
|
||||||
/// in the menu. By default it returns [CustomPopupMenuItem.child].
|
|
||||||
///
|
|
||||||
/// The [handleTap] method can be overridden to adjust exactly what happens when
|
|
||||||
/// the item is tapped. By default, it uses [Navigator.pop] to return the
|
|
||||||
/// [CustomPopupMenuItem.value] from the menu route.
|
|
||||||
///
|
|
||||||
/// This class takes two type arguments. The second, `W`, is the exact type of
|
|
||||||
/// the [Widget] that is using this [State]. It must be a subclass of
|
|
||||||
/// [CustomPopupMenuItem]. The first, `T`, must match the type argument of that widget
|
|
||||||
/// class, and is the type of values returned from this menu.
|
|
||||||
class PopupMenuItemState<T, W extends CustomPopupMenuItem<T>> extends State<W> {
|
|
||||||
/// The menu item contents.
|
|
||||||
///
|
|
||||||
/// Used by the [build] method.
|
|
||||||
///
|
|
||||||
/// By default, this returns [CustomPopupMenuItem.child]. Override this to put
|
|
||||||
/// something else in the menu entry.
|
|
||||||
@protected
|
|
||||||
Widget buildChild() => widget.child;
|
|
||||||
|
|
||||||
/// The handler for when the user selects the menu item.
|
|
||||||
///
|
|
||||||
/// Used by the [InkWell] inserted by the [build] method.
|
|
||||||
///
|
|
||||||
/// By default, uses [Navigator.pop] to return the [CustomPopupMenuItem.value] from
|
|
||||||
/// the menu route.
|
|
||||||
@protected
|
|
||||||
void handleTap() {
|
|
||||||
Navigator.pop<T>(context, widget.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final ThemeData theme = Theme.of(context);
|
|
||||||
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
|
|
||||||
TextStyle style = widget.textStyle ?? popupMenuTheme.textStyle ?? theme.textTheme.subtitle1;
|
|
||||||
|
|
||||||
if (!widget.enabled) style = style.copyWith(color: theme.disabledColor);
|
|
||||||
|
|
||||||
Widget item = AnimatedDefaultTextStyle(
|
|
||||||
style: style,
|
|
||||||
duration: kThemeChangeDuration,
|
|
||||||
child: Container(
|
|
||||||
alignment: AlignmentDirectional.centerStart,
|
|
||||||
constraints: BoxConstraints(minHeight: widget.height),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: _kMenuHorizontalPadding),
|
|
||||||
child: buildChild(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!widget.enabled) {
|
|
||||||
final bool isDark = theme.brightness == Brightness.dark;
|
|
||||||
item = IconTheme.merge(
|
|
||||||
data: IconThemeData(opacity: isDark ? 0.5 : 0.38),
|
|
||||||
child: item,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return InkWell(
|
|
||||||
onTap: widget.enabled ? handleTap : null,
|
|
||||||
canRequestFocus: widget.enabled,
|
|
||||||
child: item,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PopupMenu<T> extends StatelessWidget {
|
|
||||||
const _PopupMenu({
|
|
||||||
Key key,
|
|
||||||
this.route,
|
|
||||||
this.semanticLabel,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final _PopupMenuRoute<T> route;
|
|
||||||
final String semanticLabel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final double unit = 1.0 / (route.items.length + 1.5); // 1.0 for the width and 0.5 for the last item's fade.
|
|
||||||
final List<Widget> children = <Widget>[];
|
|
||||||
final PopupMenuThemeData popupMenuTheme = PopupMenuTheme.of(context);
|
|
||||||
|
|
||||||
for (int i = 0; i < route.items.length; i += 1) {
|
|
||||||
final double start = (i + 1) * unit;
|
|
||||||
final double end = (start + 1.5 * unit).clamp(0.0, 1.0);
|
|
||||||
final CurvedAnimation opacity = CurvedAnimation(
|
|
||||||
parent: route.animation,
|
|
||||||
curve: Interval(start, end),
|
|
||||||
);
|
|
||||||
Widget item = route.items[i];
|
|
||||||
if (route.initialValue != null && route.items[i].represents(route.initialValue)) {
|
|
||||||
item = Container(
|
|
||||||
color: Theme.of(context).highlightColor,
|
|
||||||
child: item,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
children.add(
|
|
||||||
_MenuItem(
|
|
||||||
onLayout: (Size size) {
|
|
||||||
route.itemSizes[i] = size;
|
|
||||||
},
|
|
||||||
child: FadeTransition(
|
|
||||||
opacity: opacity,
|
|
||||||
child: item,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final CurveTween opacity = CurveTween(curve: const Interval(0.0, 1.0 / 3.0));
|
|
||||||
final CurveTween width = CurveTween(curve: Interval(0.0, unit));
|
|
||||||
final CurveTween height = CurveTween(curve: Interval(0.0, unit * route.items.length));
|
|
||||||
|
|
||||||
final Widget child = ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(minWidth: _kMenuMinWidth),
|
|
||||||
child: IntrinsicWidth(
|
|
||||||
stepWidth: _kMenuWidthStep,
|
|
||||||
child: Semantics(
|
|
||||||
scopesRoute: true,
|
|
||||||
namesRoute: true,
|
|
||||||
explicitChildNodes: true,
|
|
||||||
label: semanticLabel,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: _kMenuVerticalPadding),
|
|
||||||
child: ListBody(children: children),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return AnimatedBuilder(
|
|
||||||
animation: route.animation,
|
|
||||||
builder: (BuildContext context, Widget child) {
|
|
||||||
return Opacity(
|
|
||||||
opacity: opacity.evaluate(route.animation),
|
|
||||||
child: Material(
|
|
||||||
shape: route.shape ?? popupMenuTheme.shape,
|
|
||||||
color: route.color ?? popupMenuTheme.color,
|
|
||||||
type: MaterialType.card,
|
|
||||||
elevation: route.elevation ?? popupMenuTheme.elevation ?? 8.0,
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.topEnd,
|
|
||||||
widthFactor: width.evaluate(route.animation),
|
|
||||||
heightFactor: height.evaluate(route.animation),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Positioning of the menu on the screen.
|
|
||||||
class _PopupMenuRouteLayout extends SingleChildLayoutDelegate {
|
|
||||||
_PopupMenuRouteLayout(this.position, this.itemSizes, this.selectedItemIndex, this.textDirection);
|
|
||||||
|
|
||||||
// Rectangle of underlying button, relative to the overlay's dimensions.
|
|
||||||
final RelativeRect position;
|
|
||||||
|
|
||||||
// The sizes of each item are computed when the menu is laid out, and before
|
|
||||||
// the route is laid out.
|
|
||||||
List<Size> itemSizes;
|
|
||||||
|
|
||||||
// The index of the selected item, or null if PopupMenuButton.initialValue
|
|
||||||
// was not specified.
|
|
||||||
final int selectedItemIndex;
|
|
||||||
|
|
||||||
// Whether to prefer going to the left or to the right.
|
|
||||||
final TextDirection textDirection;
|
|
||||||
|
|
||||||
// We put the child wherever position specifies, so long as it will fit within
|
|
||||||
// the specified parent size padded (inset) by 8. If necessary, we adjust the
|
|
||||||
// child's position so that it fits.
|
|
||||||
|
|
||||||
@override
|
|
||||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
|
||||||
// The menu can be at most the size of the overlay minus 8.0 pixels in each
|
|
||||||
// direction.
|
|
||||||
return BoxConstraints.loose(constraints.biggest - const Offset(_kMenuScreenPadding * 2.0, _kMenuScreenPadding * 2.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Offset getPositionForChild(Size size, Size childSize) {
|
|
||||||
// size: The size of the overlay.
|
|
||||||
// childSize: The size of the menu, when fully open, as determined by
|
|
||||||
// getConstraintsForChild.
|
|
||||||
|
|
||||||
// Find the ideal vertical position.
|
|
||||||
double y = position.top;
|
|
||||||
if (selectedItemIndex != null && itemSizes != null) {
|
|
||||||
double selectedItemOffset = _kMenuVerticalPadding;
|
|
||||||
for (int index = 0; index < selectedItemIndex; index += 1) selectedItemOffset += itemSizes[index].height;
|
|
||||||
selectedItemOffset += itemSizes[selectedItemIndex].height / 2;
|
|
||||||
y = position.top + (size.height - position.top - position.bottom) / 2.0 - selectedItemOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the ideal horizontal position.
|
|
||||||
double x;
|
|
||||||
if (position.left > position.right) {
|
|
||||||
// Menu button is closer to the right edge, so grow to the left, aligned to the right edge.
|
|
||||||
x = size.width - position.right - childSize.width;
|
|
||||||
} else if (position.left < position.right) {
|
|
||||||
// Menu button is closer to the left edge, so grow to the right, aligned to the left edge.
|
|
||||||
x = position.left;
|
|
||||||
} else {
|
|
||||||
// Menu button is equidistant from both edges, so grow in reading direction.
|
|
||||||
assert(textDirection != null);
|
|
||||||
switch (textDirection) {
|
|
||||||
case TextDirection.rtl:
|
|
||||||
x = size.width - position.right - childSize.width;
|
|
||||||
break;
|
|
||||||
case TextDirection.ltr:
|
|
||||||
x = position.left;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid going outside an area defined as the rectangle 8.0 pixels from the
|
|
||||||
// edge of the screen in every direction.
|
|
||||||
if (x < _kMenuScreenPadding)
|
|
||||||
x = _kMenuScreenPadding;
|
|
||||||
else if (x + childSize.width > size.width - _kMenuScreenPadding) x = size.width - childSize.width - _kMenuScreenPadding;
|
|
||||||
if (y < _kMenuScreenPadding)
|
|
||||||
y = _kMenuScreenPadding;
|
|
||||||
else if (y + childSize.height > size.height - _kMenuScreenPadding) y = size.height - childSize.height - _kMenuScreenPadding;
|
|
||||||
return Offset(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool shouldRelayout(_PopupMenuRouteLayout oldDelegate) {
|
|
||||||
// If called when the old and new itemSizes have been initialized then
|
|
||||||
// we expect them to have the same length because there's no practical
|
|
||||||
// way to change length of the items list once the menu has been shown.
|
|
||||||
assert(itemSizes.length == oldDelegate.itemSizes.length);
|
|
||||||
|
|
||||||
return position != oldDelegate.position ||
|
|
||||||
selectedItemIndex != oldDelegate.selectedItemIndex ||
|
|
||||||
textDirection != oldDelegate.textDirection ||
|
|
||||||
!listEquals(itemSizes, oldDelegate.itemSizes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PopupMenuRoute<T> extends PopupRoute<T> {
|
|
||||||
_PopupMenuRoute({
|
|
||||||
this.position,
|
|
||||||
this.items,
|
|
||||||
this.initialValue,
|
|
||||||
this.elevation,
|
|
||||||
this.theme,
|
|
||||||
this.popupMenuTheme,
|
|
||||||
this.barrierLabel,
|
|
||||||
this.semanticLabel,
|
|
||||||
this.shape,
|
|
||||||
this.color,
|
|
||||||
this.showMenuContext,
|
|
||||||
this.captureInheritedThemes,
|
|
||||||
this.barrierColor,
|
|
||||||
}) : itemSizes = List<Size>(items.length);
|
|
||||||
|
|
||||||
final RelativeRect position;
|
|
||||||
final List<PopupMenuEntry<T>> items;
|
|
||||||
final List<Size> itemSizes;
|
|
||||||
final dynamic initialValue;
|
|
||||||
final double elevation;
|
|
||||||
final ThemeData theme;
|
|
||||||
final String semanticLabel;
|
|
||||||
final ShapeBorder shape;
|
|
||||||
final Color color;
|
|
||||||
final PopupMenuThemeData popupMenuTheme;
|
|
||||||
final BuildContext showMenuContext;
|
|
||||||
final bool captureInheritedThemes;
|
|
||||||
final Color barrierColor;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Animation<double> createAnimation() {
|
|
||||||
return CurvedAnimation(
|
|
||||||
parent: super.createAnimation(),
|
|
||||||
curve: Curves.linear,
|
|
||||||
reverseCurve: const Interval(0.0, _kMenuCloseIntervalEnd),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Duration get transitionDuration => _kMenuDuration;
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool get barrierDismissible => true;
|
|
||||||
|
|
||||||
@override
|
|
||||||
final String barrierLabel;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
|
|
||||||
int selectedItemIndex;
|
|
||||||
if (initialValue != null) {
|
|
||||||
for (int index = 0; selectedItemIndex == null && index < items.length; index += 1) {
|
|
||||||
if (items[index].represents(initialValue)) selectedItemIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget menu = _PopupMenu<T>(route: this, semanticLabel: semanticLabel);
|
|
||||||
if (captureInheritedThemes) {
|
|
||||||
menu = InheritedTheme.captureAll(showMenuContext, menu);
|
|
||||||
} else {
|
|
||||||
// For the sake of backwards compatibility. An (unlikely) app that relied
|
|
||||||
// on having menus only inherit from the material Theme could set
|
|
||||||
// captureInheritedThemes to false and get the original behavior.
|
|
||||||
if (theme != null) menu = Theme(data: theme, child: menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
return MediaQuery.removePadding(
|
|
||||||
context: context,
|
|
||||||
removeTop: true,
|
|
||||||
removeBottom: true,
|
|
||||||
removeLeft: true,
|
|
||||||
removeRight: true,
|
|
||||||
child: Builder(
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return CustomSingleChildLayout(
|
|
||||||
delegate: _PopupMenuRouteLayout(
|
|
||||||
position,
|
|
||||||
itemSizes,
|
|
||||||
selectedItemIndex,
|
|
||||||
Directionality.of(context),
|
|
||||||
),
|
|
||||||
child: menu,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Show a popup menu that contains the `items` at `position`.
|
|
||||||
///
|
|
||||||
/// `items` should be non-null and not empty.
|
|
||||||
///
|
|
||||||
/// If `initialValue` is specified then the first item with a matching value
|
|
||||||
/// will be highlighted and the value of `position` gives the rectangle whose
|
|
||||||
/// vertical center will be aligned with the vertical center of the highlighted
|
|
||||||
/// item (when possible).
|
|
||||||
///
|
|
||||||
/// If `initialValue` is not specified then the top of the menu will be aligned
|
|
||||||
/// with the top of the `position` rectangle.
|
|
||||||
///
|
|
||||||
/// In both cases, the menu position will be adjusted if necessary to fit on the
|
|
||||||
/// screen.
|
|
||||||
///
|
|
||||||
/// Horizontally, the menu is positioned so that it grows in the direction that
|
|
||||||
/// has the most room. For example, if the `position` describes a rectangle on
|
|
||||||
/// the left edge of the screen, then the left edge of the menu is aligned with
|
|
||||||
/// the left edge of the `position`, and the menu grows to the right. If both
|
|
||||||
/// edges of the `position` are equidistant from the opposite edge of the
|
|
||||||
/// screen, then the ambient [Directionality] is used as a tie-breaker,
|
|
||||||
/// preferring to grow in the reading direction.
|
|
||||||
///
|
|
||||||
/// The positioning of the `initialValue` at the `position` is implemented by
|
|
||||||
/// iterating over the `items` to find the first whose
|
|
||||||
/// [CustomPopupMenuEntry.represents] method returns true for `initialValue`, and then
|
|
||||||
/// summing the values of [CustomPopupMenuEntry.height] for all the preceding widgets
|
|
||||||
/// in the list.
|
|
||||||
///
|
|
||||||
/// The `elevation` argument specifies the z-coordinate at which to place the
|
|
||||||
/// menu. The elevation defaults to 8, the appropriate elevation for popup
|
|
||||||
/// menus.
|
|
||||||
///
|
|
||||||
/// The `context` argument is used to look up the [Navigator] and [Theme] for
|
|
||||||
/// the menu. It is only used when the method is called. Its corresponding
|
|
||||||
/// widget can be safely removed from the tree before the popup menu is closed.
|
|
||||||
///
|
|
||||||
/// The `useRootNavigator` argument is used to determine whether to push the
|
|
||||||
/// menu to the [Navigator] furthest from or nearest to the given `context`. It
|
|
||||||
/// is `false` by default.
|
|
||||||
///
|
|
||||||
/// The `semanticLabel` argument is used by accessibility frameworks to
|
|
||||||
/// announce screen transitions when the menu is opened and closed. If this
|
|
||||||
/// label is not provided, it will default to
|
|
||||||
/// [MaterialLocalizations.popupMenuLabel].
|
|
||||||
///
|
|
||||||
/// See also:
|
|
||||||
///
|
|
||||||
/// * [CustomPopupMenuItem], a popup menu entry for a single value.
|
|
||||||
/// * [PopupMenuDivider], a popup menu entry that is just a horizontal line.
|
|
||||||
/// * [CheckedPopupMenuItem], a popup menu item with a checkmark.
|
|
||||||
/// * [PopupMenuButton], which provides an [IconButton] that shows a menu by
|
|
||||||
/// calling this method automatically.
|
|
||||||
/// * [SemanticsConfiguration.namesRoute], for a description of edge triggered
|
|
||||||
/// semantics.
|
|
||||||
Future<T> customShowMenu<T>({
|
|
||||||
@required BuildContext context,
|
|
||||||
@required RelativeRect position,
|
|
||||||
@required List<PopupMenuEntry<T>> items,
|
|
||||||
T initialValue,
|
|
||||||
double elevation,
|
|
||||||
String semanticLabel,
|
|
||||||
Color barrierColor,
|
|
||||||
ShapeBorder shape,
|
|
||||||
Color color,
|
|
||||||
bool captureInheritedThemes = true,
|
|
||||||
bool useRootNavigator = false,
|
|
||||||
}) {
|
|
||||||
assert(context != null);
|
|
||||||
assert(position != null);
|
|
||||||
assert(useRootNavigator != null);
|
|
||||||
assert(items != null && items.isNotEmpty);
|
|
||||||
assert(captureInheritedThemes != null);
|
|
||||||
assert(debugCheckHasMaterialLocalizations(context));
|
|
||||||
|
|
||||||
String label = semanticLabel;
|
|
||||||
switch (Theme.of(context).platform) {
|
|
||||||
case TargetPlatform.iOS:
|
|
||||||
case TargetPlatform.macOS:
|
|
||||||
label = semanticLabel;
|
|
||||||
break;
|
|
||||||
case TargetPlatform.android:
|
|
||||||
case TargetPlatform.fuchsia:
|
|
||||||
case TargetPlatform.linux:
|
|
||||||
case TargetPlatform.windows:
|
|
||||||
label = semanticLabel ?? MaterialLocalizations.of(context)?.popupMenuLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Navigator.of(context, rootNavigator: useRootNavigator).push(
|
|
||||||
_PopupMenuRoute<T>(
|
|
||||||
position: position,
|
|
||||||
items: items,
|
|
||||||
initialValue: initialValue,
|
|
||||||
elevation: elevation,
|
|
||||||
semanticLabel: label,
|
|
||||||
theme: Theme.of(context),
|
|
||||||
popupMenuTheme: PopupMenuTheme.of(context),
|
|
||||||
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
|
||||||
barrierColor: barrierColor,
|
|
||||||
shape: shape,
|
|
||||||
color: color,
|
|
||||||
showMenuContext: context,
|
|
||||||
captureInheritedThemes: captureInheritedThemes,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
@ -26,10 +26,10 @@ class RadarChart extends StatefulWidget {
|
|||||||
final int sides;
|
final int sides;
|
||||||
|
|
||||||
const RadarChart({
|
const RadarChart({
|
||||||
Key key,
|
Key? key,
|
||||||
@required this.ticks,
|
required this.ticks,
|
||||||
@required this.features,
|
required this.features,
|
||||||
@required this.data,
|
required this.data,
|
||||||
this.reverseAxis = false,
|
this.reverseAxis = false,
|
||||||
this.ticksTextStyle = const TextStyle(color: Colors.grey, fontSize: 12),
|
this.ticksTextStyle = const TextStyle(color: Colors.grey, fontSize: 12),
|
||||||
this.featuresTextStyle = const TextStyle(color: Colors.black, fontSize: 16),
|
this.featuresTextStyle = const TextStyle(color: Colors.black, fontSize: 16),
|
||||||
@ -40,53 +40,46 @@ class RadarChart extends StatefulWidget {
|
|||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
factory RadarChart.light({
|
factory RadarChart.light({
|
||||||
@required List<int> ticks,
|
required List<int> ticks,
|
||||||
@required List<String> features,
|
required List<String> features,
|
||||||
@required List<List<int>> data,
|
required List<List<int>> data,
|
||||||
bool reverseAxis = false,
|
bool reverseAxis = false,
|
||||||
bool useSides = false,
|
bool useSides = false,
|
||||||
}) {
|
}) {
|
||||||
return RadarChart(
|
return RadarChart(ticks: ticks, features: features, data: data, reverseAxis: reverseAxis, sides: useSides ? features.length : 0);
|
||||||
ticks: ticks,
|
|
||||||
features: features,
|
|
||||||
data: data,
|
|
||||||
reverseAxis: reverseAxis,
|
|
||||||
sides: useSides ? features.length : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory RadarChart.dark({
|
factory RadarChart.dark({
|
||||||
@required List<int> ticks,
|
required List<int> ticks,
|
||||||
@required List<String> features,
|
required List<String> features,
|
||||||
@required List<List<int>> data,
|
required List<List<int>> data,
|
||||||
bool reverseAxis = false,
|
bool reverseAxis = false,
|
||||||
bool useSides = false,
|
bool useSides = false,
|
||||||
}) {
|
}) {
|
||||||
return RadarChart(
|
return RadarChart(
|
||||||
ticks: ticks,
|
ticks: ticks,
|
||||||
features: features,
|
features: features,
|
||||||
data: data,
|
data: data,
|
||||||
featuresTextStyle: const TextStyle(color: Colors.white, fontSize: 16),
|
featuresTextStyle: const TextStyle(color: Colors.white, fontSize: 16),
|
||||||
outlineColor: Colors.white,
|
outlineColor: Colors.white,
|
||||||
axisColor: Colors.grey,
|
axisColor: Colors.grey,
|
||||||
reverseAxis: reverseAxis,
|
reverseAxis: reverseAxis,
|
||||||
sides: useSides ? features.length : 0);
|
sides: useSides ? features.length : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_RadarChartState createState() => _RadarChartState();
|
_RadarChartState createState() => _RadarChartState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RadarChartState extends State<RadarChart>
|
class _RadarChartState extends State<RadarChart> with SingleTickerProviderStateMixin {
|
||||||
with SingleTickerProviderStateMixin {
|
|
||||||
double fraction = 0;
|
double fraction = 0;
|
||||||
Animation<double> animation;
|
late Animation<double> animation;
|
||||||
AnimationController animationController;
|
late AnimationController animationController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
animationController = AnimationController(
|
animationController = AnimationController(duration: Duration(milliseconds: 1000), vsync: this);
|
||||||
duration: Duration(milliseconds: 1000), vsync: this);
|
|
||||||
|
|
||||||
animation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
|
animation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
|
||||||
curve: Curves.fastOutSlowIn,
|
curve: Curves.fastOutSlowIn,
|
||||||
@ -113,18 +106,8 @@ class _RadarChartState extends State<RadarChart>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return CustomPaint(
|
return CustomPaint(
|
||||||
size: Size(double.infinity, double.infinity),
|
size: Size(double.infinity, double.infinity),
|
||||||
painter: RadarChartPainter(
|
painter: RadarChartPainter(widget.ticks, widget.features, widget.data, widget.reverseAxis, widget.ticksTextStyle,
|
||||||
widget.ticks,
|
widget.featuresTextStyle, widget.outlineColor, widget.axisColor, widget.graphColors, widget.sides, this.fraction),
|
||||||
widget.features,
|
|
||||||
widget.data,
|
|
||||||
widget.reverseAxis,
|
|
||||||
widget.ticksTextStyle,
|
|
||||||
widget.featuresTextStyle,
|
|
||||||
widget.outlineColor,
|
|
||||||
widget.axisColor,
|
|
||||||
widget.graphColors,
|
|
||||||
widget.sides,
|
|
||||||
this.fraction),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +143,7 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
this.graphColors,
|
this.graphColors,
|
||||||
this.sides,
|
this.sides,
|
||||||
this.fraction,
|
this.fraction,
|
||||||
);
|
);
|
||||||
|
|
||||||
Path variablePath(Size size, double radius, int sides) {
|
Path variablePath(Size size, double radius, int sides) {
|
||||||
var path = Path();
|
var path = Path();
|
||||||
@ -223,14 +206,10 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
)
|
)
|
||||||
..layout(minWidth: 0, maxWidth: size.width)
|
..layout(minWidth: 0, maxWidth: size.width)
|
||||||
..paint(canvas, Offset(centerX, centerY - ticksTextStyle.fontSize));
|
..paint(canvas, Offset(centerX, centerY - ticksTextStyle.fontSize!));
|
||||||
}
|
}
|
||||||
|
|
||||||
tickLabels
|
tickLabels.sublist(reverseAxis ? 1 : 0, reverseAxis ? ticks.length : ticks.length - 1).asMap().forEach((index, tick) {
|
||||||
.sublist(
|
|
||||||
reverseAxis ? 1 : 0, reverseAxis ? ticks.length : ticks.length - 1)
|
|
||||||
.asMap()
|
|
||||||
.forEach((index, tick) {
|
|
||||||
var tickRadius = tickDistance * (index + 1);
|
var tickRadius = tickDistance * (index + 1);
|
||||||
|
|
||||||
canvas.drawPath(variablePath(size, tickRadius, this.sides), ticksPaint);
|
canvas.drawPath(variablePath(size, tickRadius, this.sides), ticksPaint);
|
||||||
@ -240,8 +219,7 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
)
|
)
|
||||||
..layout(minWidth: 0, maxWidth: size.width)
|
..layout(minWidth: 0, maxWidth: size.width)
|
||||||
..paint(canvas,
|
..paint(canvas, Offset(centerX, centerY - tickRadius - ticksTextStyle.fontSize!));
|
||||||
Offset(centerX, centerY - tickRadius - ticksTextStyle.fontSize));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Painting the axis for each given feature
|
// Painting the axis for each given feature
|
||||||
@ -251,16 +229,14 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
var xAngle = cos(angle * index - pi / 2);
|
var xAngle = cos(angle * index - pi / 2);
|
||||||
var yAngle = sin(angle * index - pi / 2);
|
var yAngle = sin(angle * index - pi / 2);
|
||||||
|
|
||||||
var featureOffset =
|
var featureOffset = Offset(centerX + radius * xAngle, centerY + radius * yAngle);
|
||||||
Offset(centerX + radius * xAngle, centerY + radius * yAngle);
|
|
||||||
|
|
||||||
canvas.drawLine(centerOffset, featureOffset, ticksPaint);
|
canvas.drawLine(centerOffset, featureOffset, ticksPaint);
|
||||||
|
|
||||||
var featureLabelFontHeight = featuresTextStyle.fontSize;
|
var featureLabelFontHeight = featuresTextStyle.fontSize;
|
||||||
var featureLabelFontWidth = featuresTextStyle.fontSize - 5;
|
var featureLabelFontWidth = featuresTextStyle.fontSize! - 5;
|
||||||
var labelYOffset = yAngle < 0 ? -featureLabelFontHeight : 0;
|
var labelYOffset = yAngle < 0 ? -featureLabelFontHeight! : 0;
|
||||||
var labelXOffset =
|
var labelXOffset = xAngle < 0 ? -featureLabelFontWidth * feature.length : 0;
|
||||||
xAngle < 0 ? -featureLabelFontWidth * feature.length : 0;
|
|
||||||
|
|
||||||
TextPainter(
|
TextPainter(
|
||||||
text: TextSpan(text: feature, style: featuresTextStyle),
|
text: TextSpan(text: feature, style: featuresTextStyle),
|
||||||
@ -268,10 +244,7 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
)
|
)
|
||||||
..layout(minWidth: 0, maxWidth: size.width)
|
..layout(minWidth: 0, maxWidth: size.width)
|
||||||
..paint(
|
..paint(canvas, Offset(featureOffset.dx + labelXOffset, featureOffset.dy + labelYOffset));
|
||||||
canvas,
|
|
||||||
Offset(featureOffset.dx + labelXOffset,
|
|
||||||
featureOffset.dy + labelYOffset));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Painting each graph
|
// Painting each graph
|
||||||
@ -304,11 +277,9 @@ class RadarChartPainter extends CustomPainter {
|
|||||||
var scaledPoint = scale * point * fraction;
|
var scaledPoint = scale * point * fraction;
|
||||||
|
|
||||||
if (reverseAxis) {
|
if (reverseAxis) {
|
||||||
path.lineTo(centerX + (radius * fraction - scaledPoint) * xAngle,
|
path.lineTo(centerX + (radius * fraction - scaledPoint) * xAngle, centerY + (radius * fraction - scaledPoint) * yAngle);
|
||||||
centerY + (radius * fraction - scaledPoint) * yAngle);
|
|
||||||
} else {
|
} else {
|
||||||
path.lineTo(
|
path.lineTo(centerX + scaledPoint * xAngle, centerY + scaledPoint * yAngle);
|
||||||
centerX + scaledPoint * xAngle, centerY + scaledPoint * yAngle);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,407 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import 'dropdown_search.dart';
|
|
||||||
|
|
||||||
class SelectDialog<T> extends StatefulWidget {
|
|
||||||
final T selectedValue;
|
|
||||||
final List<T> items;
|
|
||||||
final bool showSearchBox;
|
|
||||||
final bool isFilteredOnline;
|
|
||||||
final ValueChanged<T> onChanged;
|
|
||||||
final DropdownSearchOnFind<T> onFind;
|
|
||||||
final DropdownSearchPopupItemBuilder<T> itemBuilder;
|
|
||||||
final InputDecoration searchBoxDecoration;
|
|
||||||
final DropdownSearchItemAsString<T> itemAsString;
|
|
||||||
final DropdownSearchFilterFn<T> filterFn;
|
|
||||||
final String hintText;
|
|
||||||
final double maxHeight;
|
|
||||||
final double dialogMaxWidth;
|
|
||||||
final Widget popupTitle;
|
|
||||||
final bool showSelectedItem;
|
|
||||||
final DropdownSearchCompareFn<T> compareFn;
|
|
||||||
final DropdownSearchPopupItemEnabled<T> itemDisabled;
|
|
||||||
|
|
||||||
///custom layout for empty results
|
|
||||||
final EmptyBuilder emptyBuilder;
|
|
||||||
|
|
||||||
///custom layout for loading items
|
|
||||||
final LoadingBuilder loadingBuilder;
|
|
||||||
|
|
||||||
///custom layout for error
|
|
||||||
final ErrorBuilder errorBuilder;
|
|
||||||
|
|
||||||
///the search box will be focused if true
|
|
||||||
final bool autoFocusSearchBox;
|
|
||||||
|
|
||||||
///text controller to set default search word for example
|
|
||||||
final TextEditingController searchBoxController;
|
|
||||||
|
|
||||||
///delay before searching
|
|
||||||
final Duration searchDelay;
|
|
||||||
|
|
||||||
const SelectDialog({
|
|
||||||
Key key,
|
|
||||||
this.popupTitle,
|
|
||||||
this.items,
|
|
||||||
this.maxHeight,
|
|
||||||
this.showSearchBox = false,
|
|
||||||
this.isFilteredOnline = false,
|
|
||||||
this.onChanged,
|
|
||||||
this.selectedValue,
|
|
||||||
this.onFind,
|
|
||||||
this.itemBuilder,
|
|
||||||
this.searchBoxDecoration,
|
|
||||||
this.hintText,
|
|
||||||
this.itemAsString,
|
|
||||||
this.filterFn,
|
|
||||||
this.showSelectedItem = false,
|
|
||||||
this.compareFn,
|
|
||||||
this.emptyBuilder,
|
|
||||||
this.loadingBuilder,
|
|
||||||
this.errorBuilder,
|
|
||||||
this.autoFocusSearchBox = false,
|
|
||||||
this.dialogMaxWidth,
|
|
||||||
this.itemDisabled,
|
|
||||||
this.searchBoxController,
|
|
||||||
this.searchDelay,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_SelectDialogState<T> createState() => _SelectDialogState<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SelectDialogState<T> extends State<SelectDialog<T>> {
|
|
||||||
final FocusNode focusNode = new FocusNode();
|
|
||||||
final StreamController<List<T>> _itemsStream = StreamController();
|
|
||||||
final ValueNotifier<bool> _loadingNotifier = ValueNotifier(false);
|
|
||||||
final List<T> _items = List<T>();
|
|
||||||
Debouncer _debouncer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_debouncer = Debouncer(delay: widget.searchDelay);
|
|
||||||
|
|
||||||
Future.delayed(
|
|
||||||
Duration.zero,
|
|
||||||
() => manageItemsByFilter(widget.searchBoxController?.text ?? '', isFistLoad: true),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
if (widget.autoFocusSearchBox) FocusScope.of(context).requestFocus(focusNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_itemsStream.close();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Size deviceSize = MediaQuery.of(context).size;
|
|
||||||
bool isTablet = deviceSize.width > deviceSize.height;
|
|
||||||
double maxHeight = deviceSize.height * (isTablet ? .8 : .6);
|
|
||||||
double maxWidth = deviceSize.width * (isTablet ? .7 : .9);
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
width: widget.dialogMaxWidth ?? maxWidth,
|
|
||||||
constraints: BoxConstraints(maxHeight: widget.maxHeight ?? maxHeight),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
_searchField(),
|
|
||||||
Expanded(
|
|
||||||
child: Stack(
|
|
||||||
children: <Widget>[
|
|
||||||
StreamBuilder<List<T>>(
|
|
||||||
stream: _itemsStream.stream,
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasError) {
|
|
||||||
return _errorWidget(snapshot?.error);
|
|
||||||
} else if (!snapshot.hasData) {
|
|
||||||
return _loadingWidget();
|
|
||||||
} else if (snapshot.data.isEmpty) {
|
|
||||||
if (widget.emptyBuilder != null)
|
|
||||||
return widget.emptyBuilder(context, widget.searchBoxController?.text);
|
|
||||||
else
|
|
||||||
return const Center(
|
|
||||||
child: const Text("No data found"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return ListView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 0),
|
|
||||||
itemCount: snapshot.data.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
var item = snapshot.data[index];
|
|
||||||
return _itemWidget(item);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
_loadingWidget()
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showErrorDialog(dynamic error) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text("Error while getting online items"),
|
|
||||||
content: _errorWidget(error),
|
|
||||||
actions: <Widget>[
|
|
||||||
FlatButton(
|
|
||||||
child: new Text("OK"),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop(false);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _errorWidget(dynamic error) {
|
|
||||||
if (widget.errorBuilder != null)
|
|
||||||
return widget.errorBuilder(context, widget.searchBoxController?.text, error);
|
|
||||||
else
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.all(8),
|
|
||||||
child: Text(
|
|
||||||
error?.toString() ?? 'Error',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _loadingWidget() {
|
|
||||||
return ValueListenableBuilder(
|
|
||||||
valueListenable: _loadingNotifier,
|
|
||||||
builder: (context, bool isLoading, wid) {
|
|
||||||
if (isLoading) {
|
|
||||||
if (widget.loadingBuilder != null)
|
|
||||||
return widget.loadingBuilder(context, widget.searchBoxController?.text);
|
|
||||||
else
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(24.0),
|
|
||||||
child: const Center(
|
|
||||||
child: const CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Container();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onTextChanged(String filter) async {
|
|
||||||
manageItemsByFilter(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
///Function that filter item (online and offline) base on user filter
|
|
||||||
///[filter] is the filter keyword
|
|
||||||
///[isFirstLoad] true if it's the first time we load data from online, false other wises
|
|
||||||
void manageItemsByFilter(String filter, {bool isFistLoad = false}) async {
|
|
||||||
_loadingNotifier.value = true;
|
|
||||||
|
|
||||||
String encoded(String item) {
|
|
||||||
String encodedItem = "";
|
|
||||||
for (int i = 0; i < item.length; i++) {
|
|
||||||
var char = item[i];
|
|
||||||
switch (char) {
|
|
||||||
case 'Á':
|
|
||||||
case 'á':
|
|
||||||
case 'ą':
|
|
||||||
case 'ä':
|
|
||||||
char = 'a';
|
|
||||||
break;
|
|
||||||
case 'é':
|
|
||||||
case 'É':
|
|
||||||
char = 'e';
|
|
||||||
break;
|
|
||||||
case 'ú':
|
|
||||||
case 'ű':
|
|
||||||
case 'ü':
|
|
||||||
case 'Ú':
|
|
||||||
case 'Ű':
|
|
||||||
case 'Ü':
|
|
||||||
char = 'u';
|
|
||||||
break;
|
|
||||||
case 'ö':
|
|
||||||
case 'ő':
|
|
||||||
case 'ó':
|
|
||||||
case 'Ö':
|
|
||||||
case 'Ő':
|
|
||||||
case 'Ó':
|
|
||||||
char = 'o';
|
|
||||||
break;
|
|
||||||
case 'í':
|
|
||||||
case 'Í':
|
|
||||||
char = 'i';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
encodedItem += char;
|
|
||||||
}
|
|
||||||
return encodedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<T> applyFilter(String filter) {
|
|
||||||
return _items.where((i) {
|
|
||||||
if (widget.filterFn != null) {
|
|
||||||
return (widget.filterFn(i, filter));
|
|
||||||
} else if (i.toString().toLowerCase().contains(filter.toLowerCase()) ||
|
|
||||||
encoded(i.toString()).toLowerCase().contains(encoded(filter.toLowerCase()))) {
|
|
||||||
return true;
|
|
||||||
} else if (widget.itemAsString != null) {
|
|
||||||
bool found = (widget.itemAsString(i))?.toLowerCase()?.contains(filter.toLowerCase()) ?? false;
|
|
||||||
if (!found) {
|
|
||||||
found = (encoded(widget.itemAsString(i)))?.toLowerCase()?.contains(encoded(filter.toLowerCase())) ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
//load offline data for the first time
|
|
||||||
if (isFistLoad && widget.items != null) _items.addAll(widget.items);
|
|
||||||
|
|
||||||
//manage offline items
|
|
||||||
if (widget.onFind != null && (widget.isFilteredOnline || isFistLoad)) {
|
|
||||||
try {
|
|
||||||
final List<T> onlineItems = List();
|
|
||||||
onlineItems.addAll(await widget.onFind(filter) ?? List());
|
|
||||||
|
|
||||||
//Remove all old data
|
|
||||||
_items.clear();
|
|
||||||
//add offline items
|
|
||||||
if (widget.items != null) {
|
|
||||||
_items.addAll(widget.items);
|
|
||||||
//if filter online we filter only local list based on entred keyword (filter)
|
|
||||||
if (widget.isFilteredOnline == true) {
|
|
||||||
var filteredLocalList = applyFilter(filter);
|
|
||||||
_items.clear();
|
|
||||||
_items.addAll(filteredLocalList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//add new online items to list
|
|
||||||
_items.addAll(onlineItems);
|
|
||||||
|
|
||||||
_addDataToStream(applyFilter(filter));
|
|
||||||
} catch (e) {
|
|
||||||
_addErrorToStream(e);
|
|
||||||
//if offline items count > 0 , the error will be not visible for the user
|
|
||||||
//As solution we show it in dialog
|
|
||||||
if (widget.items != null && widget.items.isNotEmpty) {
|
|
||||||
_showErrorDialog(e);
|
|
||||||
_addDataToStream(applyFilter(filter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_addDataToStream(applyFilter(filter));
|
|
||||||
}
|
|
||||||
|
|
||||||
_loadingNotifier.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addDataToStream(List<T> data) {
|
|
||||||
if (_itemsStream.isClosed) return;
|
|
||||||
_itemsStream.add(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addErrorToStream(Object error, [StackTrace stackTrace]) {
|
|
||||||
if (_itemsStream.isClosed) return;
|
|
||||||
_itemsStream.addError(error, stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _itemWidget(T item) {
|
|
||||||
if (widget.itemBuilder != null)
|
|
||||||
return InkWell(
|
|
||||||
child: widget.itemBuilder(
|
|
||||||
context,
|
|
||||||
item,
|
|
||||||
_manageSelectedItemVisibility(item),
|
|
||||||
),
|
|
||||||
onTap: widget.itemDisabled != null && (widget.itemDisabled(item) ?? false) == true
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
Navigator.pop(context, item);
|
|
||||||
if (widget.onChanged != null) widget.onChanged(item);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
else
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
widget.itemAsString != null ? (widget.itemAsString(item) ?? "") : item.toString(),
|
|
||||||
),
|
|
||||||
selected: _manageSelectedItemVisibility(item),
|
|
||||||
onTap: widget.itemDisabled != null && (widget.itemDisabled(item) ?? false) == true
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
Navigator.pop(context, item);
|
|
||||||
if (widget.onChanged != null) widget.onChanged(item);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// selected item will be highlighted only when [widget.showSelectedItem] is true,
|
|
||||||
/// if our object is String [widget.compareFn] is not required , other wises it's required
|
|
||||||
bool _manageSelectedItemVisibility(T item) {
|
|
||||||
if (!widget.showSelectedItem) return false;
|
|
||||||
|
|
||||||
if (T == String) {
|
|
||||||
return item == widget.selectedValue;
|
|
||||||
} else {
|
|
||||||
return widget.compareFn(item, widget.selectedValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _searchField() {
|
|
||||||
return Column(crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.min, children: <Widget>[
|
|
||||||
widget.popupTitle ?? const SizedBox.shrink(),
|
|
||||||
if (widget.showSearchBox)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: TextField(
|
|
||||||
controller: widget.searchBoxController,
|
|
||||||
focusNode: focusNode,
|
|
||||||
onChanged: (f) => _debouncer(() {
|
|
||||||
_onTextChanged(f);
|
|
||||||
}),
|
|
||||||
decoration: widget.searchBoxDecoration ??
|
|
||||||
InputDecoration(
|
|
||||||
hintText: widget.hintText,
|
|
||||||
border: const OutlineInputBorder(),
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Debouncer {
|
|
||||||
final Duration delay;
|
|
||||||
Timer _timer;
|
|
||||||
|
|
||||||
Debouncer({this.delay});
|
|
||||||
|
|
||||||
call(Function action) {
|
|
||||||
_timer?.cancel();
|
|
||||||
_timer = Timer(delay ?? const Duration(milliseconds: 500), action);
|
|
||||||
}
|
|
||||||
}
|
|
70
lib/library/transparent_image.dart
Normal file
70
lib/library/transparent_image.dart
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
library transparent_image;
|
||||||
|
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
final Uint8List kTransparentImage = new Uint8List.fromList(<int>[
|
||||||
|
0x89,
|
||||||
|
0x50,
|
||||||
|
0x4E,
|
||||||
|
0x47,
|
||||||
|
0x0D,
|
||||||
|
0x0A,
|
||||||
|
0x1A,
|
||||||
|
0x0A,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x0D,
|
||||||
|
0x49,
|
||||||
|
0x48,
|
||||||
|
0x44,
|
||||||
|
0x52,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x08,
|
||||||
|
0x06,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x1F,
|
||||||
|
0x15,
|
||||||
|
0xC4,
|
||||||
|
0x89,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x0A,
|
||||||
|
0x49,
|
||||||
|
0x44,
|
||||||
|
0x41,
|
||||||
|
0x54,
|
||||||
|
0x78,
|
||||||
|
0x9C,
|
||||||
|
0x63,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x05,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
0x0D,
|
||||||
|
0x0A,
|
||||||
|
0x2D,
|
||||||
|
0xB4,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x49,
|
||||||
|
0x45,
|
||||||
|
0x4E,
|
||||||
|
0x44,
|
||||||
|
0xAE,
|
||||||
|
]);
|
@ -30,8 +30,8 @@ class TreeView extends InheritedWidget {
|
|||||||
final bool startExpanded;
|
final bool startExpanded;
|
||||||
|
|
||||||
TreeView({
|
TreeView({
|
||||||
Key key,
|
Key? key,
|
||||||
@required List<Widget> children,
|
required List<Widget> children,
|
||||||
bool startExpanded = false,
|
bool startExpanded = false,
|
||||||
}) : this.children = children,
|
}) : this.children = children,
|
||||||
this.startExpanded = startExpanded,
|
this.startExpanded = startExpanded,
|
||||||
@ -42,7 +42,7 @@ class TreeView extends InheritedWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
static TreeView of(BuildContext context) {
|
static TreeView? of(BuildContext context) {
|
||||||
return context.dependOnInheritedWidgetOfExactType(aspect: TreeView);
|
return context.dependOnInheritedWidgetOfExactType(aspect: TreeView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ class _TreeViewData extends StatefulWidget {
|
|||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
|
|
||||||
_TreeViewData({
|
_TreeViewData({
|
||||||
this.children,
|
required this.children,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -69,14 +69,14 @@ class _TreeViewData extends StatefulWidget {
|
|||||||
class __TreeViewDataState extends State<_TreeViewData> {
|
class __TreeViewDataState extends State<_TreeViewData> {
|
||||||
final ScrollController _controller = ScrollController();
|
final ScrollController _controller = ScrollController();
|
||||||
final Stream stream = TreeViewStream().stream;
|
final Stream stream = TreeViewStream().stream;
|
||||||
var subscription;
|
late var subscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
/// We require the initializers to run after the loading screen is rendered
|
/// We require the initializers to run after the loading screen is rendered
|
||||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
SchedulerBinding.instance!.addPostFrameCallback((_) {
|
||||||
final double cHeight = MediaQuery.of(context).size.height;
|
final double cHeight = MediaQuery.of(context).size.height;
|
||||||
subscription = stream.listen((value) {
|
subscription = stream.listen((value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -120,43 +120,41 @@ class __TreeViewDataState extends State<_TreeViewData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TreeViewChild extends StatefulWidget {
|
class TreeViewChild extends StatefulWidget {
|
||||||
final bool startExpanded;
|
final bool? startExpanded;
|
||||||
final Widget parent;
|
final Widget parent;
|
||||||
final List<Widget> children;
|
final List<Widget> children;
|
||||||
final VoidCallback onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
TreeViewChild({
|
TreeViewChild({
|
||||||
@required this.parent,
|
required this.parent,
|
||||||
@required this.children,
|
required this.children,
|
||||||
this.startExpanded,
|
this.startExpanded,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
Key key,
|
Key? key,
|
||||||
}) : super(key: key) {
|
}) : super(key: key);
|
||||||
assert(parent != null);
|
|
||||||
assert(children != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
TreeViewChildState createState() => TreeViewChildState();
|
TreeViewChildState createState() => TreeViewChildState();
|
||||||
|
|
||||||
TreeViewChild copyWith(
|
TreeViewChild copyWith(
|
||||||
TreeViewChild source, {
|
TreeViewChild source, {
|
||||||
bool startExpanded,
|
bool? startExpanded,
|
||||||
Widget parent,
|
Widget? parent,
|
||||||
List<Widget> children,
|
List<Widget>? children,
|
||||||
VoidCallback onTap,
|
VoidCallback? onTap,
|
||||||
}) {
|
}) {
|
||||||
return TreeViewChild(
|
return TreeViewChild(
|
||||||
parent: parent ?? source.parent,
|
parent: parent ?? source.parent,
|
||||||
children: children ?? source.children,
|
children: children ?? source.children,
|
||||||
startExpanded: startExpanded ?? source.startExpanded,
|
startExpanded: startExpanded ?? source.startExpanded,
|
||||||
onTap: onTap ?? source.onTap,
|
onTap: onTap ?? source.onTap,
|
||||||
|
key: key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TreeViewChildState extends State<TreeViewChild> with Common {
|
class TreeViewChildState extends State<TreeViewChild> with Common {
|
||||||
bool isExpanded;
|
late bool? isExpanded;
|
||||||
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
|
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -167,7 +165,7 @@ class TreeViewChildState extends State<TreeViewChild> with Common {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
isExpanded = widget.startExpanded ?? TreeView.of(context).startExpanded;
|
isExpanded = widget.startExpanded ?? TreeView.of(context)!.startExpanded;
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,17 +175,14 @@ class TreeViewChildState extends State<TreeViewChild> with Common {
|
|||||||
key: listKey,
|
key: listKey,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
GestureDetector(
|
GestureDetector(child: widget.parent, onTap: widget.onTap ?? () => toggleExpanded()),
|
||||||
child: widget.parent,
|
|
||||||
onTap: widget.onTap ?? () => toggleExpanded(),
|
|
||||||
),
|
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Container(
|
child: Container(
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: Duration(milliseconds: 200),
|
duration: Duration(milliseconds: 200),
|
||||||
reverseDuration: Duration(milliseconds: 200),
|
reverseDuration: Duration(milliseconds: 200),
|
||||||
switchInCurve: Curves.easeIn,
|
switchInCurve: Curves.easeIn,
|
||||||
child: isExpanded
|
child: isExpanded!
|
||||||
? Column(
|
? Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: widget.children,
|
children: widget.children,
|
||||||
@ -202,14 +197,14 @@ class TreeViewChildState extends State<TreeViewChild> with Common {
|
|||||||
|
|
||||||
void toggleExpanded() {
|
void toggleExpanded() {
|
||||||
setState(() {
|
setState(() {
|
||||||
this.isExpanded = !this.isExpanded;
|
this.isExpanded = !this.isExpanded!;
|
||||||
TreeViewStream().positionY = getPosition();
|
TreeViewStream().positionY = getPosition();
|
||||||
TreeViewStream().getStreamController().add(this.isExpanded);
|
TreeViewStream().getStreamController().add(this.isExpanded);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
double getPosition() {
|
double getPosition() {
|
||||||
RenderBox box = listKey.currentContext.findRenderObject();
|
RenderBox? box = listKey.currentContext!.findRenderObject() as RenderBox;
|
||||||
Offset position = box.localToGlobal(Offset.zero); //this is global position
|
Offset position = box.localToGlobal(Offset.zero); //this is global position
|
||||||
double y = position.dy;
|
double y = position.dy;
|
||||||
return y;
|
return y;
|
||||||
|
@ -6,7 +6,6 @@ import 'package:aitrainer_app/repository/workout_tree_repository.dart';
|
|||||||
import 'package:aitrainer_app/service/firebase_api.dart';
|
import 'package:aitrainer_app/service/firebase_api.dart';
|
||||||
import 'package:aitrainer_app/util/session.dart';
|
import 'package:aitrainer_app/util/session.dart';
|
||||||
import 'package:aitrainer_app/view/account.dart';
|
import 'package:aitrainer_app/view/account.dart';
|
||||||
import 'package:aitrainer_app/view/custom_exercise_page.dart';
|
|
||||||
import 'package:aitrainer_app/view/customer_bodytype_animation.dart';
|
import 'package:aitrainer_app/view/customer_bodytype_animation.dart';
|
||||||
import 'package:aitrainer_app/view/customer_exercise_device.dart';
|
import 'package:aitrainer_app/view/customer_exercise_device.dart';
|
||||||
import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
import 'package:aitrainer_app/view/customer_fitness_page.dart';
|
||||||
@ -38,7 +37,7 @@ import 'package:aitrainer_app/view/test_set_new.dart';
|
|||||||
import 'package:aitrainer_app/widgets/home.dart';
|
import 'package:aitrainer_app/widgets/home.dart';
|
||||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||||
import 'package:firebase_analytics/observer.dart';
|
import 'package:firebase_analytics/observer.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
import 'package:aitrainer_app/library/flurry.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -103,7 +102,7 @@ Future<Null> main() async {
|
|||||||
} else {
|
} else {
|
||||||
// In production mode report to the application zone to report to
|
// In production mode report to the application zone to report to
|
||||||
// Sentry.
|
// Sentry.
|
||||||
Zone.current.handleUncaughtError(details.exception, details.stack);
|
Zone.current.handleUncaughtError(details.exception, details.stack!);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,7 +133,7 @@ Future<Null> main() async {
|
|||||||
create: (BuildContext context) => MenuBloc(menuTreeRepository: menuTreeRepository),
|
create: (BuildContext context) => MenuBloc(menuTreeRepository: menuTreeRepository),
|
||||||
),
|
),
|
||||||
BlocProvider<SettingsBloc>(
|
BlocProvider<SettingsBloc>(
|
||||||
create: (BuildContext context) => SettingsBloc(),
|
create: (BuildContext context) => SettingsBloc(context: context),
|
||||||
),
|
),
|
||||||
BlocProvider<AccountBloc>(
|
BlocProvider<AccountBloc>(
|
||||||
create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
|
create: (BuildContext context) => AccountBloc(customerRepository: CustomerRepository()),
|
||||||
@ -199,13 +198,13 @@ class WorkoutTestApp extends StatelessWidget {
|
|||||||
const Locale('hu', "HU"), // Hungarian
|
const Locale('hu', "HU"), // Hungarian
|
||||||
// ... other locales the app supports
|
// ... other locales the app supports
|
||||||
],
|
],
|
||||||
localeResolutionCallback: (Locale locale, Iterable<Locale> supportedLocales) {
|
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
|
||||||
//myLocale = deviceLocale ;
|
//myLocale = deviceLocale ;
|
||||||
// here you make your app language similar to device language ,
|
// here you make your app language similar to device language ,
|
||||||
// but you should check whether the localization is supported by your app
|
// but you should check whether the localization is supported by your app
|
||||||
Locale realSupportedLocale = Locale('en', "US");
|
Locale realSupportedLocale = Locale('en', "US");
|
||||||
supportedLocales.forEach((supportedLocale) {
|
supportedLocales.forEach((supportedLocale) {
|
||||||
if (locale != null && supportedLocale != null && supportedLocale.countryCode == locale.countryCode) {
|
if (locale != null && supportedLocale.countryCode == locale.countryCode) {
|
||||||
realSupportedLocale = supportedLocale;
|
realSupportedLocale = supportedLocale;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -223,7 +222,6 @@ class WorkoutTestApp extends StatelessWidget {
|
|||||||
'customerWelcomePage': (context) => CustomerWelcomePage(),
|
'customerWelcomePage': (context) => CustomerWelcomePage(),
|
||||||
'customerExerciseDevicePage': (context) => CustomerExerciseDevicePage(),
|
'customerExerciseDevicePage': (context) => CustomerExerciseDevicePage(),
|
||||||
'exerciseNewPage': (context) => ExerciseNewPage(),
|
'exerciseNewPage': (context) => ExerciseNewPage(),
|
||||||
'exerciseCustomPage': (context) => CustomExercisePage(),
|
|
||||||
'exerciseControlPage': (context) => ExerciseControlPage(),
|
'exerciseControlPage': (context) => ExerciseControlPage(),
|
||||||
'login': (context) => LoginPage(),
|
'login': (context) => LoginPage(),
|
||||||
'resetPassword': (context) => ResetPasswordPage(),
|
'resetPassword': (context) => ResetPasswordPage(),
|
||||||
|
@ -8,6 +8,7 @@ import 'package:aitrainer_app/model/exercise_tree.dart';
|
|||||||
import 'package:aitrainer_app/model/exercise.dart';
|
import 'package:aitrainer_app/model/exercise.dart';
|
||||||
import 'package:aitrainer_app/model/model_change.dart';
|
import 'package:aitrainer_app/model/model_change.dart';
|
||||||
import 'package:aitrainer_app/model/product.dart' as wt_product;
|
import 'package:aitrainer_app/model/product.dart' as wt_product;
|
||||||
|
import 'package:aitrainer_app/model/product.dart';
|
||||||
import 'package:aitrainer_app/model/product_test.dart';
|
import 'package:aitrainer_app/model/product_test.dart';
|
||||||
import 'package:aitrainer_app/model/property.dart';
|
import 'package:aitrainer_app/model/property.dart';
|
||||||
import 'package:aitrainer_app/model/purchase.dart';
|
import 'package:aitrainer_app/model/purchase.dart';
|
||||||
@ -20,7 +21,7 @@ import 'package:aitrainer_app/main.dart';
|
|||||||
import 'package:aitrainer_app/util/enums.dart';
|
import 'package:aitrainer_app/util/enums.dart';
|
||||||
import 'package:aitrainer_app/util/env.dart';
|
import 'package:aitrainer_app/util/env.dart';
|
||||||
import 'package:aitrainer_app/util/track.dart';
|
import 'package:aitrainer_app/util/track.dart';
|
||||||
import 'package:flurry/flurry.dart';
|
import 'package:aitrainer_app/library/flurry.dart';
|
||||||
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@ -57,22 +58,22 @@ class Cache with Logging {
|
|||||||
static final Cache _singleton = Cache._internal();
|
static final Cache _singleton = Cache._internal();
|
||||||
|
|
||||||
// Keys to store and fetch data from SharedPreferences
|
// Keys to store and fetch data from SharedPreferences
|
||||||
static final String authTokenKey = 'auth_token';
|
static final String authTokenKey = "auth_token";
|
||||||
static final String customerIdKey = 'customer_id';
|
static final String customerIdKey = "customer_id";
|
||||||
static final String firebaseUidKey = 'firebase_uid';
|
static final String firebaseUidKey = "firebase_uid";
|
||||||
static final String lastStoreDateKey = 'last_date';
|
static final String lastStoreDateKey = "last_date";
|
||||||
static final String isRegisteredKey = 'is_registered';
|
static final String isRegisteredKey = "is_registered";
|
||||||
static final String isLoggedInKey = 'is_logged_in';
|
static final String isLoggedInKey = "is_logged_in";
|
||||||
static final String langKey = 'lang';
|
static final String langKey = "lang";
|
||||||
static final String serverKey = 'live';
|
static final String serverKey = "live";
|
||||||
static final String hardwareKey = 'hardware';
|
static final String hardwareKey = "hardware";
|
||||||
static final String loginTypeKey = 'login_type';
|
static final String loginTypeKey = "login_type";
|
||||||
static final String timerDisplayKey = 'timer_display';
|
static final String timerDisplayKey = "timer_display";
|
||||||
static final String activeExercisePlanKey = 'active_exercise_plan';
|
static final String activeExercisePlanKey = "active_exercise_plan";
|
||||||
static final String activeExercisePlanDateKey = 'active_exercise_plan_date';
|
static final String activeExercisePlanDateKey = "active_exercise_plan_date";
|
||||||
static final String activeExercisePlanDetailsKey = 'active_exercise_details_plan';
|
static final String activeExercisePlanDetailsKey = "active_exercise_details_plan";
|
||||||
static final String exerciseLogSeenKey = 'exercise_log_seen';
|
static final String exerciseLogSeenKey = "exercise_log_seen";
|
||||||
static final String muscleDevelopmentSeenKey = 'muscle_development_seen_key';
|
static final String muscleDevelopmentSeenKey = "muscle_development_seen_key";
|
||||||
|
|
||||||
static String baseUrl = 'http://aitrainer.info:8888/api/';
|
static String baseUrl = 'http://aitrainer.info:8888/api/';
|
||||||
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
|
static final String mediaUrl = 'https://aitrainer.info:4343/media/';
|
||||||
@ -80,51 +81,51 @@ class Cache with Logging {
|
|||||||
static final String password = 'andio2009';
|
static final String password = 'andio2009';
|
||||||
|
|
||||||
String authToken = "";
|
String authToken = "";
|
||||||
AccessToken accessTokenFacebook;
|
AccessToken? accessTokenFacebook;
|
||||||
Customer userLoggedIn;
|
Customer? userLoggedIn;
|
||||||
String firebaseUid;
|
String? firebaseUid;
|
||||||
LoginType loginType;
|
late LoginType loginType;
|
||||||
PackageInfo packageInfo;
|
late PackageInfo packageInfo;
|
||||||
|
|
||||||
bool hasPurchased = false;
|
bool hasPurchased = false;
|
||||||
|
|
||||||
bool firstLoad = true;
|
bool firstLoad = true;
|
||||||
|
|
||||||
List<ExerciseType> _exerciseTypes;
|
List<ExerciseType>? _exerciseTypes;
|
||||||
List<ExerciseTree> _exerciseTree;
|
List<ExerciseTree>? _exerciseTree;
|
||||||
|
|
||||||
List<Exercise> _exercises;
|
List<Exercise>? _exercises;
|
||||||
ExercisePlan _myExercisePlan;
|
ExercisePlan? _myExercisePlan;
|
||||||
List<Property> _properties;
|
List<Property>? _properties;
|
||||||
List<wt_product.Product> _products;
|
List<wt_product.Product>? _products;
|
||||||
List<Purchase> _purchases = List();
|
List<Purchase> _purchases = [];
|
||||||
List<ProductTest> _productTests;
|
List<ProductTest>? _productTests;
|
||||||
List<ExercisePlanTemplate> _exercisePlanTemplates = List();
|
List<ExercisePlanTemplate> _exercisePlanTemplates = [];
|
||||||
|
|
||||||
ExercisePlan activeExercisePlan;
|
ExercisePlan? activeExercisePlan;
|
||||||
List<ExercisePlanDetail> activeExercisePlanDetails;
|
List<ExercisePlanDetail>? activeExercisePlanDetails;
|
||||||
|
|
||||||
List<ExerciseDevice> _devices;
|
List<ExerciseDevice>? _devices;
|
||||||
List<CustomerExerciseDevice> _customerDevices;
|
List<CustomerExerciseDevice>? _customerDevices;
|
||||||
|
|
||||||
LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
LinkedHashMap<int, ExercisePlanDetail> _myExercisesPlanDetails = LinkedHashMap<int, ExercisePlanDetail>();
|
||||||
|
|
||||||
LinkedHashMap _tree = LinkedHashMap<String, WorkoutMenuTree>();
|
LinkedHashMap<String, WorkoutMenuTree> _tree = LinkedHashMap<String, WorkoutMenuTree>();
|
||||||
double _percentExercises = -1;
|
double _percentExercises = -1;
|
||||||
|
|
||||||
Customer _trainee;
|
Customer? _trainee;
|
||||||
List<Exercise> _exercisesTrainee;
|
List<Exercise>? _exercisesTrainee;
|
||||||
ExercisePlan _traineeExercisePlan;
|
ExercisePlan? _traineeExercisePlan;
|
||||||
|
|
||||||
LinkedHashMap<String, int> _badges = LinkedHashMap();
|
LinkedHashMap<String, int> _badges = LinkedHashMap();
|
||||||
|
|
||||||
List deviceLanguages;
|
List? deviceLanguages;
|
||||||
String startPage = "home";
|
String startPage = "home";
|
||||||
String testEnvironment;
|
late String testEnvironment;
|
||||||
bool liveServer = true;
|
bool liveServer = true;
|
||||||
bool hasHardware = false;
|
bool? hasHardware = false;
|
||||||
bool isExerciseLogSeen = false;
|
bool? isExerciseLogSeen = false;
|
||||||
bool isMuscleDevelopmentSeen = false;
|
bool? isMuscleDevelopmentSeen = false;
|
||||||
|
|
||||||
factory Cache() {
|
factory Cache() {
|
||||||
return _singleton;
|
return _singleton;
|
||||||
@ -186,11 +187,8 @@ class Cache with Logging {
|
|||||||
|
|
||||||
DateFormat format = DateFormat("yyyy-MM-dd HH:mm:ss");
|
DateFormat format = DateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
DateTime savedPlanDate;
|
DateTime savedPlanDate;
|
||||||
try {
|
|
||||||
savedPlanDate = format.parse(savedPlanDateString);
|
savedPlanDate = format.parse(savedPlanDateString);
|
||||||
} on Exception catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final DateTime now = DateTime.now();
|
final DateTime now = DateTime.now();
|
||||||
final DateTime added = savedPlanDate.add(Duration(days: 1));
|
final DateTime added = savedPlanDate.add(Duration(days: 1));
|
||||||
@ -198,13 +196,13 @@ class Cache with Logging {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String exercisePlanJson = sharedPreferences.getString(Cache.activeExercisePlanKey);
|
String? exercisePlanJson = sharedPreferences.getString(Cache.activeExercisePlanKey);
|
||||||
if (exercisePlanJson != null) {
|
if (exercisePlanJson != null) {
|
||||||
final Map<String, dynamic> map = JsonDecoder().convert(exercisePlanJson);
|
final Map<String, dynamic> map = JsonDecoder().convert(exercisePlanJson);
|
||||||
this.activeExercisePlan = ExercisePlan.fromJson(map);
|
this.activeExercisePlan = ExercisePlan.fromJson(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
String detailsJson = sharedPreferences.getString(Cache.activeExercisePlanDetailsKey);
|
String? detailsJson = sharedPreferences.getString(Cache.activeExercisePlanDetailsKey);
|
||||||
if (detailsJson != null) {
|
if (detailsJson != null) {
|
||||||
print("Details $detailsJson");
|
print("Details $detailsJson");
|
||||||
Iterable json = jsonDecode(detailsJson);
|
Iterable json = jsonDecode(detailsJson);
|
||||||
@ -225,7 +223,7 @@ class Cache with Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getHardware(SharedPreferences prefs) {
|
void getHardware(SharedPreferences prefs) {
|
||||||
final bool hasHardware = prefs.getBool(Cache.hardwareKey);
|
final bool? hasHardware = prefs.getBool(Cache.hardwareKey);
|
||||||
this.hasHardware = hasHardware;
|
this.hasHardware = hasHardware;
|
||||||
if (hasHardware == null) {
|
if (hasHardware == null) {
|
||||||
this.hasHardware = false;
|
this.hasHardware = false;
|
||||||
@ -236,7 +234,7 @@ class Cache with Logging {
|
|||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
|
|
||||||
final bool selectedHardware = sharedPreferences.getBool(Cache.hardwareKey);
|
final bool? selectedHardware = sharedPreferences.getBool(Cache.hardwareKey);
|
||||||
return selectedHardware == null;
|
return selectedHardware == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +252,7 @@ class Cache with Logging {
|
|||||||
print("TestEnv $baseUrl");
|
print("TestEnv $baseUrl");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final bool live = prefs.getBool(Cache.serverKey);
|
final bool? live = prefs.getBool(Cache.serverKey);
|
||||||
if (live == null) {
|
if (live == null) {
|
||||||
baseUrl = 'http://aitrainer.app:8888/api/';
|
baseUrl = 'http://aitrainer.app:8888/api/';
|
||||||
print("Live Env $baseUrl");
|
print("Live Env $baseUrl");
|
||||||
@ -274,7 +272,7 @@ class Cache with Logging {
|
|||||||
Future<void> setLoginTypeFromPrefs() async {
|
Future<void> setLoginTypeFromPrefs() async {
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
final String loginType = sharedPreferences.getString(Cache.loginTypeKey);
|
final String? loginType = sharedPreferences.getString(Cache.loginTypeKey);
|
||||||
LoginType type = LoginType.email;
|
LoginType type = LoginType.email;
|
||||||
if (loginType == LoginType.apple.toString()) {
|
if (loginType == LoginType.apple.toString()) {
|
||||||
type = LoginType.apple;
|
type = LoginType.apple;
|
||||||
@ -289,7 +287,7 @@ class Cache with Logging {
|
|||||||
Cache().setLoginType(type);
|
Cache().setLoginType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getToken(SharedPreferences prefs) {
|
static String? getToken(SharedPreferences prefs) {
|
||||||
return prefs.getString(authTokenKey);
|
return prefs.getString(authTokenKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,10 +303,10 @@ class Cache with Logging {
|
|||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
|
|
||||||
userLoggedIn = customer;
|
userLoggedIn = customer;
|
||||||
final String uid = Cache().firebaseUid;
|
final String uid = Cache().firebaseUid!;
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
||||||
await setPreferences(prefs, SharePrefsChange.registration, customer.customerId, uid);
|
await setPreferences(prefs, SharePrefsChange.registration, customer.customerId!, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
afterLogin(Customer customer) async {
|
afterLogin(Customer customer) async {
|
||||||
@ -317,21 +315,21 @@ class Cache with Logging {
|
|||||||
userLoggedIn = customer;
|
userLoggedIn = customer;
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
||||||
await setPreferences(prefs, SharePrefsChange.login, customer.customerId, Cache().firebaseUid);
|
await setPreferences(prefs, SharePrefsChange.login, customer.customerId!, Cache().firebaseUid!);
|
||||||
}
|
}
|
||||||
|
|
||||||
afterFirebaseLogin() async {
|
afterFirebaseLogin() async {
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
||||||
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().firebaseUid);
|
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn!.customerId!, Cache().firebaseUid!);
|
||||||
}
|
}
|
||||||
|
|
||||||
afterFacebookLogin() async {
|
afterFacebookLogin() async {
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
SharedPreferences sharedPreferences = await prefs;
|
SharedPreferences sharedPreferences = await prefs;
|
||||||
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
sharedPreferences.setString(Cache.loginTypeKey, Cache().getLoginType().toString());
|
||||||
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn.customerId, Cache().firebaseUid);
|
await setPreferences(prefs, SharePrefsChange.login, userLoggedIn!.customerId!, Cache().firebaseUid!);
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() async {
|
logout() async {
|
||||||
@ -345,7 +343,7 @@ class Cache with Logging {
|
|||||||
_percentExercises = -1;
|
_percentExercises = -1;
|
||||||
_exercisesTrainee = null;
|
_exercisesTrainee = null;
|
||||||
_traineeExercisePlan = null;
|
_traineeExercisePlan = null;
|
||||||
_exercises = List();
|
_exercises = [];
|
||||||
_myExercisesPlanDetails = LinkedHashMap();
|
_myExercisesPlanDetails = LinkedHashMap();
|
||||||
log("Trainees is null? " + (_trainee == null).toString());
|
log("Trainees is null? " + (_trainee == null).toString());
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
@ -372,7 +370,7 @@ class Cache with Logging {
|
|||||||
} else if (type == SharePrefsChange.logout) {
|
} else if (type == SharePrefsChange.logout) {
|
||||||
sharedPreferences.setBool(Cache.isLoggedInKey, false);
|
sharedPreferences.setBool(Cache.isLoggedInKey, false);
|
||||||
sharedPreferences.setInt(Cache.customerIdKey, 0);
|
sharedPreferences.setInt(Cache.customerIdKey, 0);
|
||||||
sharedPreferences.setString(Cache.firebaseUidKey, null);
|
sharedPreferences.setString(Cache.firebaseUidKey, "");
|
||||||
sharedPreferences.setString(authTokenKey, "");
|
sharedPreferences.setString(authTokenKey, "");
|
||||||
}
|
}
|
||||||
initBadges();
|
initBadges();
|
||||||
@ -396,23 +394,25 @@ class Cache with Logging {
|
|||||||
this._tree = tree;
|
this._tree = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExerciseType> getExerciseTypes() => this._exerciseTypes;
|
List<ExerciseType>? getExerciseTypes() => this._exerciseTypes;
|
||||||
|
|
||||||
ExerciseType getExerciseTypeById(int exerciseTypeId) {
|
ExerciseType? getExerciseTypeById(int exerciseTypeId) {
|
||||||
ExerciseType exerciseType;
|
ExerciseType? exerciseType;
|
||||||
this._exerciseTypes.forEach((element) {
|
if (_exerciseTypes != null) {
|
||||||
if (element.exerciseTypeId == exerciseTypeId) {
|
this._exerciseTypes!.forEach((element) {
|
||||||
exerciseType = element;
|
if (element.exerciseTypeId == exerciseTypeId) {
|
||||||
}
|
exerciseType = element;
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return exerciseType;
|
return exerciseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<ExerciseTree> getExerciseTree() => this._exerciseTree;
|
List<ExerciseTree>? getExerciseTree() => this._exerciseTree;
|
||||||
|
|
||||||
List<Exercise> getExercises() => this._exercises;
|
List<Exercise>? getExercises() => this._exercises;
|
||||||
|
|
||||||
List<Exercise> getExercisesTrainee() => this._exercisesTrainee;
|
List<Exercise>? getExercisesTrainee() => this._exercisesTrainee;
|
||||||
|
|
||||||
LinkedHashMap<String, WorkoutMenuTree> getWorkoutMenuTree() => this._tree;
|
LinkedHashMap<String, WorkoutMenuTree> getWorkoutMenuTree() => this._tree;
|
||||||
|
|
||||||
@ -420,21 +420,21 @@ class Cache with Logging {
|
|||||||
|
|
||||||
double getPercentExercises() => this._percentExercises;
|
double getPercentExercises() => this._percentExercises;
|
||||||
|
|
||||||
void addExercise(Exercise exercise) => _exercises.add(exercise);
|
void addExercise(Exercise exercise) => _exercises!.add(exercise);
|
||||||
|
|
||||||
void addExerciseTrainee(Exercise exercise) => _exercisesTrainee.add(exercise);
|
void addExerciseTrainee(Exercise exercise) => _exercisesTrainee!.add(exercise);
|
||||||
|
|
||||||
Customer getTrainee() => this._trainee;
|
Customer? getTrainee() => this._trainee;
|
||||||
|
|
||||||
void setTrainee(Customer trainee) => _trainee = trainee;
|
void setTrainee(Customer trainee) => _trainee = trainee;
|
||||||
|
|
||||||
void setTraineeExercisePlan(ExercisePlan exercisePlan) => this._traineeExercisePlan = exercisePlan;
|
void setTraineeExercisePlan(ExercisePlan exercisePlan) => this._traineeExercisePlan = exercisePlan;
|
||||||
|
|
||||||
ExercisePlan getTraineesExercisePlan() => this._traineeExercisePlan;
|
ExercisePlan? getTraineesExercisePlan() => this._traineeExercisePlan;
|
||||||
|
|
||||||
void setMyExercisePlan(ExercisePlan exercisePlan) => _myExercisePlan = exercisePlan;
|
void setMyExercisePlan(ExercisePlan exercisePlan) => _myExercisePlan = exercisePlan;
|
||||||
|
|
||||||
ExercisePlan getMyExercisePlan() => _myExercisePlan;
|
ExercisePlan? getMyExercisePlan() => _myExercisePlan;
|
||||||
|
|
||||||
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) =>
|
void setMyExercisePlanDetails(LinkedHashMap<int, ExercisePlanDetail> listExercisePlanDetail) =>
|
||||||
_myExercisesPlanDetails = listExercisePlanDetail;
|
_myExercisesPlanDetails = listExercisePlanDetail;
|
||||||
@ -452,30 +452,30 @@ class Cache with Logging {
|
|||||||
void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId);
|
void deleteMyExercisePlanDetail(ExercisePlanDetail detail) => this.deleteMyExercisePlanDetailByExerciseTypeId(detail.exerciseTypeId);
|
||||||
|
|
||||||
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) =>
|
void deletedMyExercisePlanDetail(ExercisePlanDetail detail) =>
|
||||||
this._myExercisesPlanDetails[detail.exerciseTypeId].change = ModelChange.deleted;
|
this._myExercisesPlanDetails[detail.exerciseTypeId]!.change = ModelChange.deleted;
|
||||||
|
|
||||||
void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) {
|
void deleteMyExercisePlanDetailByExerciseTypeId(int exerciseTypeId) {
|
||||||
this._myExercisesPlanDetails[exerciseTypeId].change = ModelChange.delete;
|
this._myExercisesPlanDetails[exerciseTypeId]!.change = ModelChange.delete;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setProperties(List<Property> properties) => this._properties = properties;
|
void setProperties(List<Property> properties) => this._properties = properties;
|
||||||
|
|
||||||
List<Property> getProperties() => _properties;
|
List<Property>? getProperties() => _properties;
|
||||||
|
|
||||||
void setDevices(List<ExerciseDevice> devices) => this._devices = devices;
|
void setDevices(List<ExerciseDevice> devices) => this._devices = devices;
|
||||||
|
|
||||||
List<ExerciseDevice> getDevices() => this._devices;
|
List<ExerciseDevice>? getDevices() => this._devices;
|
||||||
|
|
||||||
void setCustomerDevices(List<CustomerExerciseDevice> devices) => this._customerDevices = devices;
|
void setCustomerDevices(List<CustomerExerciseDevice> devices) => this._customerDevices = devices;
|
||||||
|
|
||||||
List<CustomerExerciseDevice> getCustomerDevices() => this._customerDevices;
|
List<CustomerExerciseDevice>? getCustomerDevices() => this._customerDevices;
|
||||||
|
|
||||||
LinkedHashMap getBadges() => _badges;
|
LinkedHashMap getBadges() => _badges;
|
||||||
|
|
||||||
void setBadge(String key, bool inc) {
|
void setBadge(String key, bool inc) {
|
||||||
if (inc) {
|
if (inc) {
|
||||||
if (_badges[key] != null) {
|
if (_badges[key] != null) {
|
||||||
_badges[key]++;
|
_badges[key] = _badges[key]! + 1;
|
||||||
} else {
|
} else {
|
||||||
_badges[key] = 1;
|
_badges[key] = 1;
|
||||||
}
|
}
|
||||||
@ -484,7 +484,7 @@ class Cache with Logging {
|
|||||||
if (_badges[key] == 1) {
|
if (_badges[key] == 1) {
|
||||||
_badges.remove(key);
|
_badges.remove(key);
|
||||||
} else {
|
} else {
|
||||||
_badges[key]--;
|
_badges[key] = _badges[key]! - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,31 +492,34 @@ class Cache with Logging {
|
|||||||
|
|
||||||
void setBadgeNr(String key, int counter) {
|
void setBadgeNr(String key, int counter) {
|
||||||
if (_badges[key] != null) {
|
if (_badges[key] != null) {
|
||||||
_badges[key] += counter;
|
_badges[key] = _badges[key]! + counter;
|
||||||
} else {
|
} else {
|
||||||
_badges[key] = counter;
|
_badges[key] = counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void initBadges() async {
|
void initBadges() {
|
||||||
CustomerRepository customerRepository = CustomerRepository();
|
CustomerRepository customerRepository = CustomerRepository();
|
||||||
_badges = LinkedHashMap();
|
_badges = LinkedHashMap();
|
||||||
customerRepository.setCustomer(userLoggedIn);
|
if (userLoggedIn == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
customerRepository.setCustomer(userLoggedIn!);
|
||||||
int _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt();
|
int _ecto = customerRepository.getCustomerPropertyValue(PropertyEnum.Ectomorph.toStr()).toInt();
|
||||||
int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
int _mezo = customerRepository.getCustomerPropertyValue(PropertyEnum.Mesomorph.toStr()).toInt();
|
||||||
int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt();
|
int _endo = customerRepository.getCustomerPropertyValue(PropertyEnum.Endomorph.toStr()).toInt();
|
||||||
|
|
||||||
//print("endo " + _endo.toString() + " mezo " + _mezo.toString());
|
//print("endo " + _endo.toString() + " mezo " + _mezo.toString());
|
||||||
if (this.userLoggedIn != null) {
|
if (this.userLoggedIn != null) {
|
||||||
if (this.userLoggedIn.birthYear == null || this.userLoggedIn.birthYear == 0) {
|
if (this.userLoggedIn!.birthYear == null || this.userLoggedIn!.birthYear == 0) {
|
||||||
setBadge("personalData", true);
|
setBadge("personalData", true);
|
||||||
setBadge("account", true);
|
setBadge("account", true);
|
||||||
}
|
}
|
||||||
if (this._customerDevices == null || this._customerDevices.isEmpty) {
|
if (this._customerDevices == null || this._customerDevices!.isEmpty) {
|
||||||
setBadge("customerDevice", true);
|
setBadge("customerDevice", true);
|
||||||
setBadge("account", true);
|
setBadge("account", true);
|
||||||
}
|
}
|
||||||
if (userLoggedIn.properties == null || userLoggedIn.properties.isEmpty) {
|
if (userLoggedIn!.properties.isEmpty) {
|
||||||
setBadge("personalData", true);
|
setBadge("personalData", true);
|
||||||
setBadge("bodyType", true);
|
setBadge("bodyType", true);
|
||||||
setBadge("Sizes", true);
|
setBadge("Sizes", true);
|
||||||
@ -534,7 +537,7 @@ class Cache with Logging {
|
|||||||
setBadge("account", true);
|
setBadge("account", true);
|
||||||
setBadge("bodyType", true);
|
setBadge("bodyType", true);
|
||||||
}
|
}
|
||||||
if (this._exercises == null || this._exercises.length == 0) {
|
if (this._exercises == null || this._exercises!.isEmpty) {
|
||||||
setBadge("home", true);
|
setBadge("home", true);
|
||||||
setBadge("Muscle Build / Shape Toning", true);
|
setBadge("Muscle Build / Shape Toning", true);
|
||||||
setBadge("Cardio", true);
|
setBadge("Cardio", true);
|
||||||
@ -545,20 +548,20 @@ class Cache with Logging {
|
|||||||
setBadge("My Body", true);
|
setBadge("My Body", true);
|
||||||
setBadgeNr("home", 1);
|
setBadgeNr("home", 1);
|
||||||
}
|
}
|
||||||
if (userLoggedIn.goal == null) {
|
if (userLoggedIn!.goal == null) {
|
||||||
setBadge("Goal", true);
|
setBadge("Goal", true);
|
||||||
setBadge("account", true);
|
setBadge("account", true);
|
||||||
}
|
}
|
||||||
if (userLoggedIn.fitnessLevel == null) {
|
if (userLoggedIn!.fitnessLevel == null) {
|
||||||
setBadge("FitnessLevel", true);
|
setBadge("FitnessLevel", true);
|
||||||
setBadge("account", true);
|
setBadge("account", true);
|
||||||
}
|
}
|
||||||
if (this._exercises != null && this._exercises.isNotEmpty) {
|
if (this._exercises != null && this._exercises!.isNotEmpty) {
|
||||||
if (!isExerciseLogSeen) {
|
if (!isExerciseLogSeen!) {
|
||||||
setBadge("exerciseLog", true);
|
setBadge("exerciseLog", true);
|
||||||
setBadge("development", true);
|
setBadge("development", true);
|
||||||
}
|
}
|
||||||
if (!isMuscleDevelopmentSeen) {
|
if (!isMuscleDevelopmentSeen!) {
|
||||||
setBadge("muscleDevelopment", true);
|
setBadge("muscleDevelopment", true);
|
||||||
setBadge("development", true);
|
setBadge("development", true);
|
||||||
}
|
}
|
||||||
@ -567,14 +570,16 @@ class Cache with Logging {
|
|||||||
log("Badges: " + _badges.toString());
|
log("Badges: " + _badges.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
List get products => _products;
|
List<Product>? get products => _products;
|
||||||
void setProducts(List value) => _products = value;
|
void setProducts(List<wt_product.Product> value) => _products = value;
|
||||||
|
|
||||||
List get purchases => _purchases;
|
List<Purchase> get purchases => _purchases;
|
||||||
setPurchases(List value) => _purchases = value;
|
setPurchases(List<Purchase> value) => _purchases = value;
|
||||||
|
|
||||||
List get productTests => _productTests;
|
// ignore: unnecessary_getters_setters
|
||||||
set productTests(List value) => _productTests = value;
|
List<ProductTest>? get productTests => _productTests;
|
||||||
|
// ignore: unnecessary_getters_setters
|
||||||
|
set productTests(List<ProductTest>? value) => _productTests = value;
|
||||||
|
|
||||||
Future<void> initCustomer(int customerId) async {
|
Future<void> initCustomer(int customerId) async {
|
||||||
log(" *** initCustomer");
|
log(" *** initCustomer");
|
||||||
@ -593,10 +598,10 @@ class Cache with Logging {
|
|||||||
Cache().startPage = "home";
|
Cache().startPage = "home";
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessToken get getAccessTokenFacebook => accessTokenFacebook;
|
AccessToken? get getAccessTokenFacebook => accessTokenFacebook;
|
||||||
set setAccessTokenFacebook(AccessToken accessTokenFacebook) => this.accessTokenFacebook = accessTokenFacebook;
|
set setAccessTokenFacebook(AccessToken accessTokenFacebook) => this.accessTokenFacebook = accessTokenFacebook;
|
||||||
|
|
||||||
LoginType getLoginType() => loginType;
|
LoginType? getLoginType() => loginType;
|
||||||
void setLoginType(LoginType type) => this.loginType = type;
|
void setLoginType(LoginType type) => this.loginType = type;
|
||||||
|
|
||||||
List get exercisePlanTemplates => this._exercisePlanTemplates;
|
List get exercisePlanTemplates => this._exercisePlanTemplates;
|
||||||
@ -617,7 +622,7 @@ class Cache with Logging {
|
|||||||
isExerciseLogSeen = false;
|
isExerciseLogSeen = false;
|
||||||
}
|
}
|
||||||
//print("ExerciseLogSeen $isExerciseLogSeen");
|
//print("ExerciseLogSeen $isExerciseLogSeen");
|
||||||
return isExerciseLogSeen;
|
return isExerciseLogSeen!;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMuscleDevelopmentSeen() async {
|
setMuscleDevelopmentSeen() async {
|
||||||
@ -634,6 +639,6 @@ class Cache with Logging {
|
|||||||
if (isMuscleDevelopmentSeen == null) {
|
if (isMuscleDevelopmentSeen == null) {
|
||||||
isMuscleDevelopmentSeen = false;
|
isMuscleDevelopmentSeen = false;
|
||||||
}
|
}
|
||||||
return isMuscleDevelopmentSeen;
|
return isMuscleDevelopmentSeen!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
import 'customer_property.dart';
|
import 'customer_property.dart';
|
||||||
|
|
||||||
class Customer {
|
class Customer {
|
||||||
String name;
|
String? name;
|
||||||
String email;
|
late String? email;
|
||||||
String firstname;
|
String? firstname;
|
||||||
String sex;
|
String? sex;
|
||||||
int age;
|
int? age;
|
||||||
String active;
|
String? active;
|
||||||
int customerId;
|
int? customerId;
|
||||||
String password;
|
String? password;
|
||||||
int birthYear;
|
int? birthYear;
|
||||||
String goal;
|
String? goal;
|
||||||
String fitnessLevel;
|
String? fitnessLevel;
|
||||||
String bodyType;
|
String? bodyType;
|
||||||
int admin;
|
int? admin;
|
||||||
int trainer;
|
int? trainer;
|
||||||
int dataPolicyAllowed;
|
int? dataPolicyAllowed;
|
||||||
String firebaseUid;
|
String? firebaseUid;
|
||||||
DateTime dateAdd;
|
DateTime? dateAdd;
|
||||||
DateTime dateChange;
|
DateTime? dateChange;
|
||||||
|
|
||||||
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
|
LinkedHashMap<String, CustomerProperty> properties = LinkedHashMap();
|
||||||
|
|
||||||
@ -43,7 +43,10 @@ class Customer {
|
|||||||
this.dataPolicyAllowed,
|
this.dataPolicyAllowed,
|
||||||
this.firebaseUid,
|
this.firebaseUid,
|
||||||
this.dateAdd,
|
this.dateAdd,
|
||||||
this.dateChange});
|
this.dateChange}) {
|
||||||
|
dateAdd = DateTime.now();
|
||||||
|
dateChange = DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
Customer.fromJson(Map json) {
|
Customer.fromJson(Map json) {
|
||||||
this.customerId = json['customerId'];
|
this.customerId = json['customerId'];
|
||||||
@ -81,19 +84,19 @@ class Customer {
|
|||||||
"admin": admin,
|
"admin": admin,
|
||||||
"trainer": trainer,
|
"trainer": trainer,
|
||||||
"dataPolicyAllowed": dataPolicyAllowed,
|
"dataPolicyAllowed": dataPolicyAllowed,
|
||||||
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd),
|
"dateAdd": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateAdd!),
|
||||||
"dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange),
|
"dateChange": DateFormat('yyyy-MM-dd HH:mm:ss').format(this.dateChange!),
|
||||||
};
|
};
|
||||||
|
|
||||||
double getProperty(String propertyName) {
|
double getProperty(String propertyName) {
|
||||||
if (this.properties[propertyName] == null) {
|
if (this.properties[propertyName] == null) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return this.properties[propertyName].propertyValue;
|
return this.properties[propertyName]!.propertyValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setProperty(String propertyName, double value) {
|
setProperty(String propertyName, double value) {
|
||||||
this.properties[propertyName].propertyValue = value;
|
this.properties[propertyName]!.propertyValue = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class CustomerExerciseDevice {
|
class CustomerExerciseDevice {
|
||||||
int customerExerciseDeviceId;
|
int? customerExerciseDeviceId;
|
||||||
int exerciseDeviceId;
|
late int exerciseDeviceId;
|
||||||
int customerId;
|
late int customerId;
|
||||||
bool favourite;
|
late bool favourite;
|
||||||
DateTime dateAdd;
|
late DateTime dateAdd;
|
||||||
|
|
||||||
String change;
|
late String change;
|
||||||
|
|
||||||
CustomerExerciseDevice({this.exerciseDeviceId, this.customerId, this.favourite}) {
|
CustomerExerciseDevice({required this.exerciseDeviceId, required this.customerId, required this.favourite}) {
|
||||||
dateAdd = DateTime.now();
|
dateAdd = DateTime.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user