Compare commits

...

10 Commits

Author SHA1 Message Date
Tibor Bossanyi (Freelancer)
45cebbbdd2 v.1.28.2 save exercise async 2023-01-20 07:53:04 +01:00
Tibor Bossanyi (Freelancer)
a8af8f7c7e v1.1.28 builder 2023-01-18 16:38:28 +01:00
bossanyit
3f52d95bbf v1.27.1 error fixes 2023-01-15 11:45:30 +01:00
Tibor Bossanyi (Freelancer)
98901f2770 v1.1.27 deactivate customer 2022-11-26 16:46:06 +01:00
Tibor Bossanyi (Freelancer)
dbdcf2f239 v1.1.27 posthog_session integration 2022-11-22 23:34:02 +01:00
Tibor Bossanyi (Freelancer)
ba36a10790 v1.1.26 release, mode 2022-11-15 07:41:04 +01:00
Tibor Bossanyi (Freelancer)
cbaa1a5b81 v1.1.26+110 android release 2022-11-13 21:26:27 +01:00
bossanyit
6ef311286c v1.1.26 android release 2022-11-13 09:43:49 +01:00
bossanyit
20c481298f v1.26 ios v2 readme 2022-10-29 10:02:50 +02:00
bossanyit
621d766335 v1.26 ios v2 2022-10-29 10:01:00 +02:00
95 changed files with 8224 additions and 903 deletions

View File

@ -2,5 +2,7 @@
The WorkoutTest Mobile Application
live 1.1.22
live 1.1.26

View File

@ -22,12 +22,12 @@
</natures>
<filteredResources>
<filter>
<id>1633186029325</id>
<id>1666112134141</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>

View File

@ -33,8 +33,6 @@ if (keystorePropertiesFile.exists()) {
}
android {
compileSdkVersion 31
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
@ -45,16 +43,16 @@ android {
defaultConfig {
applicationId "com.aitrainer.aitrainer_app"
minSdkVersion 20
targetSdkVersion 30
minSdkVersion 21
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
ndk.abiFilters 'armeabi-v7a', 'arm64-v8a','x86_64'
}
android {
compileSdkVersion 33
}
signingConfigs {
@ -85,6 +83,9 @@ dependencies {
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.firebase:firebase-messaging:20.1.0'
implementation 'com.google.firebase:firebase-core:20.0.0'
implementation('com.google.firebase:firebase-auth') {
exclude module: "play-services-safetynet"
}
implementation 'com.google.firebase:firebase-inappmessaging-display:20.1.1'
}
sourceCompatibility = '1.8'

View File

@ -8,7 +8,7 @@
<application android:name="${applicationName}" android:label="WorkoutTest" android:icon="@mipmap/launcher_icon">
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id" />
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/facebook_client_token"/>
<activity android:name="io.flutter.embedding.android.FlutterActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize" android:allowBackup="false" android:fullBackupContent="false">
<activity android:name="io.flutter.embedding.android.FlutterActivity" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize" android:allowBackup="false" android:fullBackupContent="false" android:exported="true">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
@ -47,7 +47,7 @@
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity" android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" />
"keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" android:exported="false"/>
<activity android:name="com.facebook.CustomTabActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@ -56,8 +56,14 @@
<data android:scheme="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>
<meta-data android:name="com.posthog.posthog.API_KEY" android:value="phc_ATsS8RRdgzDdKpDSPYEYpYxWjfZ4QPMHHnoLbSaTZ2Q" />
<meta-data android:name="com.posthog.posthog.POSTHOG_HOST" android:value="https://posthog.workouttest.org" />
<meta-data android:name="com.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS" android:value="true" />
<meta-data android:name="com.posthog.posthog.DEBUG" android:value="true" />
</application>
<queries>
<provider android:authorities="com.facebook.katana.provider.PlatformProvider" />
<provider android:authorities="com.facebook.katana.provider.PlatformProvider" android:exported="false"/>
</queries>
</manifest>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_adaptive_back"/>
<foreground android:drawable="@mipmap/ic_launcher_adaptive_fore"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.gms:google-services:4.3.4"
}

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip

7216
android/my-logs.txt Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 5.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
asset/image/cardio_time.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -1,218 +1,210 @@
PODS:
- AppAuth (1.5.0):
- AppAuth/Core (= 1.5.0)
- AppAuth/ExternalUserAgent (= 1.5.0)
- AppAuth/Core (1.5.0)
- AppAuth/ExternalUserAgent (1.5.0):
- AppAuth (1.6.0):
- AppAuth/Core (= 1.6.0)
- AppAuth/ExternalUserAgent (= 1.6.0)
- AppAuth/Core (1.6.0)
- AppAuth/ExternalUserAgent (1.6.0):
- AppAuth/Core
- device_info_plus (0.0.1):
- Flutter
- devicelocale (0.0.1):
- Flutter
- FBAEMKit (13.0.0):
- FBSDKCoreKit_Basics (= 13.0.0)
- FBSDKCoreKit (13.0.0):
- FBAEMKit (= 13.0.0)
- FBSDKCoreKit_Basics (= 13.0.0)
- FBSDKCoreKit_Basics (13.0.0)
- FBSDKLoginKit (13.0.0):
- FBSDKCoreKit (= 13.0.0)
- Firebase/Analytics (8.11.0):
- FBAEMKit (14.1.0):
- FBSDKCoreKit_Basics (= 14.1.0)
- FBSDKCoreKit (14.1.0):
- FBAEMKit (= 14.1.0)
- FBSDKCoreKit_Basics (= 14.1.0)
- FBSDKCoreKit_Basics (14.1.0)
- FBSDKLoginKit (14.1.0):
- FBSDKCoreKit (= 14.1.0)
- Firebase/Analytics (10.0.0):
- Firebase/Core
- Firebase/Auth (8.11.0):
- Firebase/Auth (10.0.0):
- Firebase/CoreOnly
- FirebaseAuth (~> 8.11.0)
- Firebase/Core (8.11.0):
- FirebaseAuth (~> 10.0.0)
- Firebase/Core (10.0.0):
- Firebase/CoreOnly
- FirebaseAnalytics (~> 8.11.0)
- Firebase/CoreOnly (8.11.0):
- FirebaseCore (= 8.11.0)
- Firebase/DynamicLinks (8.11.0):
- FirebaseAnalytics (~> 10.0.0)
- Firebase/CoreOnly (10.0.0):
- FirebaseCore (= 10.0.0)
- Firebase/DynamicLinks (10.0.0):
- Firebase/CoreOnly
- FirebaseDynamicLinks (~> 8.11.0)
- Firebase/InAppMessaging (8.11.0):
- FirebaseDynamicLinks (~> 10.0.0)
- Firebase/InAppMessaging (10.0.0):
- Firebase/CoreOnly
- FirebaseInAppMessaging (~> 8.11.0-beta)
- Firebase/Messaging (8.11.0):
- FirebaseInAppMessaging (~> 10.0.0-beta)
- Firebase/Messaging (10.0.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 8.11.0)
- Firebase/RemoteConfig (8.11.0):
- FirebaseMessaging (~> 10.0.0)
- Firebase/RemoteConfig (10.0.0):
- Firebase/CoreOnly
- FirebaseRemoteConfig (~> 8.11.0)
- firebase_analytics (9.1.2):
- Firebase/Analytics (= 8.11.0)
- FirebaseRemoteConfig (~> 10.0.0)
- firebase_analytics (10.0.1):
- Firebase/Analytics (= 10.0.0)
- firebase_core
- Flutter
- firebase_auth (3.3.11):
- Firebase/Auth (= 8.11.0)
- firebase_auth (4.0.1):
- Firebase/Auth (= 10.0.0)
- firebase_core
- Flutter
- firebase_core (1.13.1):
- Firebase/CoreOnly (= 8.11.0)
- firebase_core (2.0.0):
- Firebase/CoreOnly (= 10.0.0)
- Flutter
- firebase_dynamic_links (4.1.1):
- Firebase/DynamicLinks (= 8.11.0)
- firebase_dynamic_links (5.0.1):
- Firebase/DynamicLinks (= 10.0.0)
- firebase_core
- Flutter
- firebase_in_app_messaging (0.6.0-9):
- Firebase/InAppMessaging (= 8.11.0)
- firebase_in_app_messaging (0.7.0-1):
- Firebase/InAppMessaging (= 10.0.0)
- firebase_core
- Flutter
- firebase_messaging (11.2.11):
- Firebase/Messaging (= 8.11.0)
- firebase_messaging (14.0.1):
- Firebase/Messaging (= 10.0.0)
- firebase_core
- Flutter
- firebase_remote_config (2.0.2):
- Firebase/RemoteConfig (= 8.11.0)
- firebase_remote_config (3.0.1):
- Firebase/RemoteConfig (= 10.0.0)
- firebase_core
- Flutter
- FirebaseABTesting (8.14.0):
- FirebaseCore (~> 8.0)
- FirebaseAnalytics (8.11.0):
- FirebaseAnalytics/AdIdSupport (= 8.11.0)
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (~> 2.30908.0)
- FirebaseAnalytics/AdIdSupport (8.11.0):
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleAppMeasurement (= 8.11.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (~> 2.30908.0)
- FirebaseAuth (8.11.0):
- FirebaseCore (~> 8.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/Environment (~> 7.7)
- GTMSessionFetcher/Core (~> 1.5)
- FirebaseCore (8.11.0):
- FirebaseCoreDiagnostics (~> 8.0)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- FirebaseCoreDiagnostics (8.14.0):
- GoogleDataTransport (~> 9.1)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Logger (~> 7.7)
- nanopb (~> 2.30908.0)
- FirebaseDynamicLinks (8.11.0):
- FirebaseCore (~> 8.0)
- FirebaseInAppMessaging (8.11.0-beta):
- FirebaseABTesting (~> 8.0)
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleUtilities/Environment (~> 7.7)
- nanopb (~> 2.30908.0)
- FirebaseInstallations (8.14.0):
- FirebaseCore (~> 8.0)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/UserDefaults (~> 7.7)
- PromisesObjC (< 3.0, >= 1.2)
- FirebaseMessaging (8.11.0):
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleDataTransport (~> 9.1)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/Environment (~> 7.7)
- GoogleUtilities/Reachability (~> 7.7)
- GoogleUtilities/UserDefaults (~> 7.7)
- nanopb (~> 2.30908.0)
- FirebaseRemoteConfig (8.11.0):
- FirebaseABTesting (~> 8.0)
- FirebaseCore (~> 8.0)
- FirebaseInstallations (~> 8.0)
- GoogleUtilities/Environment (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- FirebaseABTesting (10.0.0):
- FirebaseCore (~> 10.0)
- FirebaseAnalytics (10.0.0):
- FirebaseAnalytics/AdIdSupport (= 10.0.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.0.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.0.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseAuth (10.0.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GTMSessionFetcher/Core (~> 2.1)
- FirebaseCore (10.0.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreInternal (10.0.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseDynamicLinks (10.0.0):
- FirebaseCore (~> 10.0)
- FirebaseInAppMessaging (10.0.0-beta):
- FirebaseABTesting (~> 10.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseInstallations (10.0.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.0.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseRemoteConfig (10.0.0):
- FirebaseABTesting (~> 10.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- Flutter (1.0.0)
- flutter_app_badger (0.0.1):
- Flutter
- flutter_facebook_auth (4.1.2):
- FBSDKCoreKit (~> 13.0.0)
- FBSDKLoginKit (~> 13.0.0)
- flutter_facebook_auth (4.4.1):
- FBSDKLoginKit (= 14.1.0)
- Flutter
- flutter_secure_storage (3.3.1):
- Flutter
- flutter_smartlook (0.0.5):
- google_sign_in_ios (0.0.1):
- Flutter
- flutter_uxcam (2.0.1):
- Flutter
- UXCam (~> 3.3.6)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- google_sign_in (0.0.1):
- Flutter
- GoogleSignIn (~> 5.0)
- GoogleAppMeasurement (8.11.0):
- GoogleAppMeasurement/AdIdSupport (= 8.11.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (~> 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (8.11.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 8.11.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (~> 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (8.11.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.7)
- GoogleUtilities/MethodSwizzler (~> 7.7)
- GoogleUtilities/Network (~> 7.7)
- "GoogleUtilities/NSData+zlib (~> 7.7)"
- nanopb (~> 2.30908.0)
- GoogleDataTransport (9.1.2):
- GoogleUtilities/Environment (~> 7.2)
- nanopb (~> 2.30908.0)
- GoogleSignIn (~> 6.2)
- GoogleAppMeasurement (10.0.0):
- GoogleAppMeasurement/AdIdSupport (= 10.0.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.0.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.0.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.0.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleDataTransport (9.2.0):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleSignIn (5.0.2):
- AppAuth (~> 1.2)
- GTMAppAuth (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1)
- GoogleUtilities/AppDelegateSwizzler (7.7.0):
- GoogleSignIn (6.2.4):
- AppAuth (~> 1.5)
- GTMAppAuth (~> 1.3)
- GTMSessionFetcher/Core (< 3.0, >= 1.1)
- GoogleUtilities/AppDelegateSwizzler (7.8.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (7.7.0):
- GoogleUtilities/Environment (7.8.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/Logger (7.7.0):
- GoogleUtilities/Logger (7.8.0):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (7.7.0):
- GoogleUtilities/MethodSwizzler (7.8.0):
- GoogleUtilities/Logger
- GoogleUtilities/Network (7.7.0):
- GoogleUtilities/Network (7.8.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (7.7.0)"
- GoogleUtilities/Reachability (7.7.0):
- "GoogleUtilities/NSData+zlib (7.8.0)"
- GoogleUtilities/Reachability (7.8.0):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.7.0):
- GoogleUtilities/UserDefaults (7.8.0):
- GoogleUtilities/Logger
- GTMAppAuth (1.2.3):
- AppAuth/Core (~> 1.4)
- GTMSessionFetcher/Core (~> 1.5)
- GTMSessionFetcher/Core (1.7.1)
- GTMAppAuth (1.3.1):
- AppAuth/Core (~> 1.6)
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
- GTMSessionFetcher/Core (2.1.0)
- modal_progress_hud_nsn (0.0.1):
- Flutter
- nanopb (2.30908.0):
- nanopb/decode (= 2.30908.0)
- nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30908.0)
- nanopb/encode (2.30908.0)
- nanopb (2.30909.0):
- nanopb/decode (= 2.30909.0)
- nanopb/encode (= 2.30909.0)
- nanopb/decode (2.30909.0)
- nanopb/encode (2.30909.0)
- package_info (0.0.1):
- Flutter
- package_info_plus (0.4.5):
- Flutter
- path_provider_ios (0.0.1):
- Flutter
- PromisesObjC (2.1.0)
- PostHog (1.4.4)
- posthog_session (0.0.1):
- Flutter
- PostHog (~> 1.1)
- PromisesObjC (2.1.1)
- Purchases (3.13.2):
- PurchasesCoreSwift (= 3.13.2)
- purchases_flutter (3.9.5):
@ -221,25 +213,21 @@ PODS:
- PurchasesCoreSwift (3.13.2)
- PurchasesHybridCommon (1.11.2):
- Purchases (= 3.13.2)
- Sentry (7.10.2):
- Sentry/Core (= 7.10.2)
- Sentry/Core (7.10.2)
- Sentry (7.28.0):
- Sentry/Core (= 7.28.0)
- Sentry/Core (7.28.0)
- sentry_flutter (0.0.1):
- Flutter
- FlutterMacOS
- Sentry (~> 7.10.1)
- Sentry (~> 7.28.0)
- share (0.0.1):
- Flutter
- shared_preferences_ios (0.0.1):
- Flutter
- sign_in_with_apple (0.0.1):
- Flutter
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- url_launcher_ios (0.0.1):
- Flutter
- UXCam (3.3.9)
- video_player_avfoundation (0.0.1):
- Flutter
- wakelock (0.0.1):
@ -261,19 +249,17 @@ DEPENDENCIES:
- flutter_app_badger (from `.symlinks/plugins/flutter_app_badger/ios`)
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- flutter_smartlook (from `.symlinks/plugins/flutter_smartlook/ios`)
- flutter_uxcam (from `.symlinks/plugins/flutter_uxcam/ios`)
- google_sign_in (from `.symlinks/plugins/google_sign_in/ios`)
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
- modal_progress_hud_nsn (from `.symlinks/plugins/modal_progress_hud_nsn/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- posthog_session (from `.symlinks/plugins/posthog_session/ios`)
- purchases_flutter (from `.symlinks/plugins/purchases_flutter/ios`)
- sentry_flutter (from `.symlinks/plugins/sentry_flutter/ios`)
- share (from `.symlinks/plugins/share/ios`)
- shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`)
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
@ -291,13 +277,12 @@ SPEC REPOS:
- FirebaseAnalytics
- FirebaseAuth
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseCoreInternal
- FirebaseDynamicLinks
- FirebaseInAppMessaging
- FirebaseInstallations
- FirebaseMessaging
- FirebaseRemoteConfig
- FMDB
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleSignIn
@ -305,12 +290,12 @@ SPEC REPOS:
- GTMAppAuth
- GTMSessionFetcher
- nanopb
- PostHog
- PromisesObjC
- Purchases
- PurchasesCoreSwift
- PurchasesHybridCommon
- Sentry
- UXCam
EXTERNAL SOURCES:
device_info_plus:
@ -339,12 +324,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
flutter_smartlook:
:path: ".symlinks/plugins/flutter_smartlook/ios"
flutter_uxcam:
:path: ".symlinks/plugins/flutter_uxcam/ios"
google_sign_in:
:path: ".symlinks/plugins/google_sign_in/ios"
google_sign_in_ios:
:path: ".symlinks/plugins/google_sign_in_ios/ios"
modal_progress_hud_nsn:
:path: ".symlinks/plugins/modal_progress_hud_nsn/ios"
package_info:
@ -353,6 +334,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
posthog_session:
:path: ".symlinks/plugins/posthog_session/ios"
purchases_flutter:
:path: ".symlinks/plugins/purchases_flutter/ios"
sentry_flutter:
@ -363,8 +346,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/shared_preferences_ios/ios"
sign_in_with_apple:
:path: ".symlinks/plugins/sign_in_with_apple/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
video_player_avfoundation:
@ -375,63 +356,60 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/webview_flutter_wkwebview/ios"
SPEC CHECKSUMS:
AppAuth: 80317d99ac7ff2801a2f18ff86b48cd315ed465d
AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
devicelocale: b22617f40038496deffba44747101255cee005b0
FBAEMKit: 11a0bcdc7a88e26ed764bcf56372afc6cbbbdcd9
FBSDKCoreKit: 00e1e751257e1005304fa29cb683d2dfe008f41a
FBSDKCoreKit_Basics: 96ec2ddb67a032e54f0754ea3d59db6f84f42389
FBSDKLoginKit: 66ff4ddf372d9c3fc360e65ae048a47a482c29b9
Firebase: 44dd9724c84df18b486639e874f31436eaa9a20c
firebase_analytics: 20841ef6a705a412c737deb2fe98290e9242d323
firebase_auth: bdfbd5b10da1db6d5eb6ae7dbda5d81365b9cc9d
firebase_core: 08f6a85f62060111de5e98d6a214810d11365de9
firebase_dynamic_links: 1b6e3aeb743c0a0df1dab3543bd9dec6aab4de58
firebase_in_app_messaging: 5937abf8acacbe3d35123a4c845ccf9d1669d7ed
firebase_messaging: 4a993bb4aa1a83349988d853c637fbb0494dab15
firebase_remote_config: 588bafe2eff61076e53b018758ec1fa96893e3c3
FirebaseABTesting: aaa0e096c9fc9972ce6806d596e8fcc077d4371f
FirebaseAnalytics: 4e4b13031034e6561ed3bd1d47b6fdabbd6487c6
FirebaseAuth: d96d73aba85d192d7a7aa0b86dd6d7f8ec170b4b
FirebaseCore: 2f4f85b453cc8fea4bb2b37e370007d2bcafe3f0
FirebaseCoreDiagnostics: fd0c8490f34287229c1d6c103d3a55f81ec85712
FirebaseDynamicLinks: f506c83eb7eba0f9861f84cd6b65c38b3bd5ff6f
FirebaseInAppMessaging: 68586d72d5411b2dfaeb02461c2cd8d9f96a771a
FirebaseInstallations: 7d1d967a307c12f1aadd76844fc321cef699b1ce
FirebaseMessaging: 02e248e8997f71fa8cc9d78e9d49ec1a701ba14a
FirebaseRemoteConfig: a6a1ce9dabf404817ae2a44e8421d276660d9091
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a
FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792
FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98
FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660
Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf
firebase_analytics: 8f6874ecf36f61797835ed99d7a792d3a212b026
firebase_auth: 62015b6cbfccf40521d7f777c804d19f9bc6f922
firebase_core: f9febc855bab615ea02dc9a75b6932364edb1225
firebase_dynamic_links: 37282d0148b844b34d09a9aba54bfa72eada9377
firebase_in_app_messaging: 3ec946b7cf90c3fb0257e1e8155180d6dbf644f7
firebase_messaging: a39df674ecaffd962658a9de3182d735b6cee0d7
firebase_remote_config: 11eee0656374e6ef595f36e49d904ddc209b4523
FirebaseABTesting: 5a08a4d3060b7fb5638f60698bc2cb57996bcc73
FirebaseAnalytics: 9921a52739f4ab66099da31b6e0243db78a3ac0a
FirebaseAuth: 493382cf533cc45e2862b00e9aa4cfe4c98daf71
FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995
FirebaseCoreInternal: 5eb3960335da5ea30115d57d39db6988c4ad06f3
FirebaseDynamicLinks: 37dcd9f082b9c5ea9eb5826e82aef58bbd6fd5c1
FirebaseInAppMessaging: 07aafacbb74228af034fb1c8885d25045a25d510
FirebaseInstallations: 7f1c9ae6bd9df6abe9c74124b38fa8740aba5df4
FirebaseMessaging: 8916bf5edb1dbfac74665a181e4d1ab3a78a08a2
FirebaseRemoteConfig: e4431ddba74ddf705e2aabd7d356a23d5b802853
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_app_badger: 65de4d6f0c34a891df49e6cfb8a1c0496426fa68
flutter_facebook_auth: c0a8473f857cf44b0a27bfe752facf1d5fedd863
flutter_facebook_auth: 361ac7a57263ebf327f26089507ead0d66558ee8
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
flutter_smartlook: 2aa304f6a38fc22b741ca750e0078606582525ae
flutter_uxcam: 32e4e8b4355be6bf9d512ad36aed6d86c98a5cdf
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
google_sign_in: f669f45933dad48cd218dc3e189726bced3d19f4
GoogleAppMeasurement: aa3cb422fab2b05d2efac543a5720d1a85b9dea5
GoogleDataTransport: 629c20a4d363167143f30ea78320d5a7eb8bd940
GoogleSignIn: 7137d297ddc022a7e0aa4619c86d72c909fa7213
GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1
GTMAppAuth: 987526d41b07efb1bedda5e936fe0cb718a03113
GTMSessionFetcher: 4577a4cc914a5a07c40a8a0ad0acc22080418c2d
google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c
GoogleAppMeasurement: 7e48a3249792ac35d6f18f107f63f199a7e9d0ce
GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f
GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a
GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f
modal_progress_hud_nsn: f6fb744cd060653d66ed8f325360ef3650eb2fde
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
PromisesObjC: 99b6f43f9e1044bd87a95a60beff28c2c44ddb72
PostHog: 4b6321b521569092d4ef3a02238d9435dbaeb99f
posthog_session: 24d7e00a2ebd7586c8e7a1789b987f3f8d6cd10a
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
Purchases: 03200de9288724e77de435000d1828601e6b8e00
purchases_flutter: cf2b742f12b7ffef6f618c7f1ba1961e652825b1
PurchasesCoreSwift: 2ea4b33e5cece5c8a0751594ef7c6cbfcbd747a9
PurchasesHybridCommon: 56ef42d85c3e930d49aff4ac5fa027373d2e1bb8
Sentry: 7bf9bfe713692cf87812e55f0999260494ba7982
sentry_flutter: 77ccdac346608b8ce7e428e7284e7a3e4e7f4a02
Sentry: 2c6053e4cfe6dea6608135dea1928ffbb4ecfba5
sentry_flutter: fad3ef0917dc1afa7d242af0743696ed9a9a8864
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de
UXCam: fb294bf954e708fc308a645ae65bb967cac0760e
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
webview_flutter_wkwebview: 005fbd90c888a42c5690919a1527ecc6649e1162

View File

@ -160,7 +160,6 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
EB0A62903CC30EC853FC7908 /* [CP] Embed Pods Frameworks */,
C1BA2CB9D651F269CCBE06B3 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -270,23 +269,6 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
C1BA2CB9D651F269CCBE06B3 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
EB0A62903CC30EC853FC7908 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -388,6 +370,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
@ -405,9 +389,10 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.26;
MARKETING_VERSION = 1.1.27;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
@ -531,6 +516,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
@ -548,9 +535,10 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.26;
MARKETING_VERSION = 1.1.27;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -566,6 +554,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = SFJJBDCU6Z;
ENABLE_BITCODE = NO;
@ -583,9 +573,10 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 1.1.26;
MARKETING_VERSION = 1.1.27;
PRODUCT_BUNDLE_IDENTIFIER = com.aitrainer.app;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;

View File

@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
@ -38,10 +40,10 @@
<string>TRUE</string>
<key>FacebookAppID</key>
<string>584181112271127</string>
<key>FacebookClientToken</key>
<string>60d565f451ce32de3d7eeb26274bbddd</string>
<key>FacebookAutoLogAppEventsEnabled</key>
<string>TRUE</string>
<key>FacebookClientToken</key>
<string>60d565f451ce32de3d7eeb26274bbddd</string>
<key>FacebookDisplayName</key>
<string>Workout Test</string>
<key>FirebaseAppDelegateProxyEnabled</key>
@ -98,5 +100,13 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>com.posthog.posthog.API_KEY</key>
<string>phc_ATsS8RRdgzDdKpDSPYEYpYxWjfZ4QPMHHnoLbSaTZ2Q</string>
<key>com.posthog.posthog.POSTHOG_HOST</key>
<string>https://posthog.workouttest.org</string>
<key>com.posthog.posthog.TRACK_APPLICATION_LIFECYCLE_EVENTS</key>
<false/>
</dict>
</plist>

View File

@ -6,6 +6,8 @@ import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:meta/meta.dart';
import '../../service/customer_service.dart';
part 'account_event.dart';
part 'account_state.dart';
@ -21,6 +23,7 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
on<AccountLogout>(_onLogout);
on<AccountGetTrainees>(_onGetTrainees);
on<AccountSelectTrainee>(_onSelectTrainees);
on<DeleteAccount>(_onDeleteAccount);
}
void _load() {
@ -56,6 +59,24 @@ class AccountBloc extends Bloc<AccountEvent, AccountState> {
emit(AccountReady());
}
void _onDeleteAccount(DeleteAccount event, Emitter<AccountState> emit) async {
emit(AccountLoading());
await Cache().logout();
customerRepository.customer = event.customer;
customerRepository.emptyTrainees();
loggedIn = false;
//delete local store
int customerId = customerRepository.customer!.customerId!;
await Cache().deleteCustomerId(customerId);
customerRepository.customer = null;
// deactivate user
await CustomerApi().deactivateCustomer(customerId);
emit(AccountReady());
}
void _onGetTrainees(AccountGetTrainees event, Emitter<AccountState> emit) async {
emit(AccountLoading());
await customerRepository.getTrainees();

View File

@ -20,6 +20,14 @@ class AccountLogin extends AccountEvent {
const AccountLogin();
}
class DeleteAccount extends AccountEvent {
final Customer customer;
const DeleteAccount ({required this.customer});
@override
List<Object> get props => [customer];
}
class AccountLogInFinished extends AccountEvent {
final Customer customer;

View File

@ -133,26 +133,29 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
void _onSaveFitness(CustomerSaveFitness event, Emitter<CustomerChangeState> emit) {
emit(CustomerChangeLoading());
if (customerRepository.customer!.fitnessLevel == null) {
throw Exception("Please select your fitness level");
}
emit(CustomerSaveError(message: "Please select your fitness level"));
} else {
emit(CustomerSaveSuccess());
}
}
void _onSaveGoal(CustomerSaveGoal event, Emitter<CustomerChangeState> emit) {
emit(CustomerChangeLoading());
if (customerRepository.customer!.goal == null) {
throw Exception("Please select your goal");
}
emit(CustomerSaveError(message: "Please select your goal"));
} else {
emit(CustomerSaveSuccess());
}
}
void _onSaveSex(CustomerSaveSex event, Emitter<CustomerChangeState> emit) {
emit(CustomerChangeLoading());
if (customerRepository.customer!.sex == null) {
throw Exception("Please select your biologial gender");
}
emit(CustomerSaveError(message: "Please select your biological gender"));
} else {
emit(CustomerSaveSuccess());
}
}
void _onSaveWeight(CustomerSaveWeight event, Emitter<CustomerChangeState> emit) {
emit(CustomerChangeLoading());
@ -166,6 +169,7 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
void _onSave(CustomerSave event, Emitter<CustomerChangeState> emit) async {
emit(CustomerSaving());
try {
if (validation()) {
if (selectedFitnessItem != null) {
customerRepository.setFitnessLevel(selectedFitnessItem!);
@ -186,6 +190,9 @@ class CustomerChangeBloc extends Bloc<CustomerChangeEvent, CustomerChangeState>
} else {
emit(CustomerSaveError(message: "Please provide the necessary information"));
}
} on Exception catch (e) {
emit(CustomerSaveError(message: e.toString()));
}
}
void _load() {

View File

@ -1,6 +1,6 @@
import 'package:aitrainer_app/repository/mautic_repository.dart';
import 'package:intl/intl.dart';
import 'package:aitrainer_app/main.dart';
import 'package:flutter/foundation.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
@ -174,15 +174,15 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
}
exerciseRepository.end = DateTime.now();
await exerciseRepository.addExercise();
if (!isInDebugMode) {
exerciseRepository.addExercise();
if (kReleaseMode) {
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
await mauticRepository.sendMauticExercise();
mauticRepository.sendMauticExercise();
}
menuBloc.add(MenuTreeDown(parent: 0));
Cache().initBadges();
Track().track(TrackingEvent.exercise_new, eventValue: exerciseRepository.exerciseType!.name);
emit(ExerciseNewReady());
emit(ExerciseNewSaved());
}
void _onSubmitNoRegistration(ExerciseNewSubmitNoRegistration event, Emitter<ExerciseNewState> emit) async {
@ -190,7 +190,7 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
exerciseRepository.addExerciseNoRegistration();
menuBloc.add(MenuTreeDown(parent: 0));
Track().track(TrackingEvent.exercise_new_no_registration, eventValue: exerciseRepository.exerciseType!.name);
emit(ExerciseNewReady());
emit(ExerciseNewSaved());
}
void _onBMIAnimate(ExerciseNewBMIAnimate event, Emitter<ExerciseNewState> emit) async {
@ -220,7 +220,12 @@ class ExerciseNewBloc extends Bloc<ExerciseNewEvent, ExerciseNewState> with Logg
double getBMR() {
var date = DateTime.now();
if (weight == null || height == null || height == 0 || weight == 0) {
if (weight == null ||
height == null ||
height == 0 ||
weight == 0 ||
customerRepository.customer == null ||
customerRepository.customer!.birthYear == null) {
this.bmi = 0;
return 0;
}

View File

@ -93,10 +93,10 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
Track().track(TrackingEvent.login, eventValue: "email");
Cache().setLoginType(LoginType.email);
} on Exception catch(e) {
emit(LoginError(message: e.toString()));
} finally {
emit(LoginSuccess());
} on Exception catch (e) {
print("Login error: $e" );
emit(LoginError(message: e.toString()));
}
}
@ -107,10 +107,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
await userRepository.getUserByFB();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
Track().track(TrackingEvent.login, eventValue: "FB");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
} finally {
emit(LoginSuccess());
}
}
@ -121,11 +120,9 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
await userRepository.getUserByGoogle();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
Track().track(TrackingEvent.login, eventValue: "Google");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
} finally {
emit(LoginSuccess());
}
}
@ -136,15 +133,15 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
await userRepository.getUserByApple();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
Track().track(TrackingEvent.login, eventValue: "Apple");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
} finally {
emit(LoginSuccess());
}
}
void _onRegistrationSubmit(RegistrationSubmit event, Emitter<LoginState> emit) async {
emit(LoginLoading());
try {
final String? validationError = this.validate();
if (validationError != null) {
emit(LoginError(message: validationError));
@ -154,38 +151,59 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> with Trans {
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
await afterRegistration("email");
Cache().setLoginType(LoginType.email);
}
emit(LoginSuccess());
}
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
return;
}
}
void _onRegistrationFB(RegistrationFB event, Emitter<LoginState> emit) async {
emit(LoginLoading());
try {
Cache().setLoginType(LoginType.fb);
await userRepository.addUserFB();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
await afterRegistration("FB");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
}
}
void _onRegistrationGoogle(RegistrationGoogle event, Emitter<LoginState> emit) async {
emit(LoginLoading());
try {
Cache().setLoginType(LoginType.google);
await userRepository.addUserGoogle();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
await afterRegistration("Google");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
}
}
void _onRegistrationApple(RegistrationApple event, Emitter<LoginState> emit) async {
emit(LoginLoading());
try {
Cache().setLoginType(LoginType.apple);
await userRepository.addUserApple();
accountBloc.add(AccountLogInFinished(customer: Cache().userLoggedIn!));
customerRepository!.customer!.emailSubscription = emailSubscription == true ? 1 : 0;
await afterRegistration("Apple");
emit(LoginSuccess());
} on Exception catch (e) {
emit(LoginError(message: e.toString()));
}
}
void _onDataProtectionClicked(DataProtectionClicked event, Emitter<LoginState> emit) async {

View File

@ -113,103 +113,6 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> with Trans, Logging {
this.context = context;
}
/* @override
Stream<MenuState> mapEventToState(
MenuEvent event,
) async* {
try {
if (event is MenuCreate) {
yield MenuLoading();
//await menuTreeRepository.createTree();
//menuTreeRepository.getBranch(this.parent);
//setMenuInfo();
if (Cache().getDevices() != null) {
exerciseDeviceRepository.setDevices(Cache().getDevices()!);
}
yield MenuReady();
} else if (event is MenuRecreateTree) {
yield MenuLoading();
// ie. at language changes
menuTreeRepository.createTree();
yield MenuReady();
} else if (event is MenuTreeDown) {
yield MenuLoading();
parent = event.parent;
workoutItem = event.item;
if (workoutItem != null) {
setAbility(workoutItem!.internalName);
}
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(event.parent);
await getImages(branch);
yield MenuReady();
} else if (event is MenuTreeUp) {
yield MenuLoading();
// get parent menus or exercises
parent = event.parent;
workoutItem = menuTreeRepository.getParentItem(parent);
LinkedHashMap<String, WorkoutMenuTree> branch;
if (workoutItem != null) {
setAbility(workoutItem!.internalName);
branch = menuTreeRepository.getBranch(workoutItem!.parent);
await getImages(branch);
}
yield MenuReady();
} else if (event is MenuTreeJump) {
yield MenuLoading();
parent = event.parent;
workoutItem = menuTreeRepository.getParentItem(parent);
if (workoutItem != null) {
setAbility(workoutItem!.internalName);
}
final LinkedHashMap<String, WorkoutMenuTree> branch = menuTreeRepository.getBranch(workoutItem!.parent);
await getImages(branch);
yield MenuReady();
} else if (event is MenuClickExercise) {
yield MenuLoading();
// get exercise page
yield MenuReady();
} else if (event is MenuFilterExerciseType) {
yield MenuLoading();
final int deviceId = event.deviceId;
if (selectedDevice(deviceId)) {
listFilterDevice.add(deviceId);
} else {
listFilterDevice.remove(deviceId);
}
yield MenuReady();
} else if (event is MenuStartTrial) {
yield MenuLoading();
final DateTime start = event.start;
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = Cache().userLoggedIn;
customerRepository.customer!.trialDate = start;
Cache().userLoggedIn!.trialDate = start;
customerRepository.saveCustomer();
if (DateTime.now().difference(start).inHours < 1) {
Cache().hasPurchased = true;
log("Trial mode on!");
Track().track(TrackingEvent.trial, eventValue: DateFormat('yyyy-MM-dd HH:mm:ss').format(start));
if (!isInDebugMode) {
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);
await mauticRepository.sendMauticTrial();
}
}
yield MenuReady();
}
} on Exception catch (ex) {
yield MenuError(message: ex.toString());
}
} */
void setAbility(String name) {
switch (name) {
case "one_rep_max":

View File

@ -15,7 +15,10 @@ import 'package:aitrainer_app/util/purchases.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/services.dart';
import 'package:purchases_flutter/errors.dart';
import 'package:purchases_flutter/models/offering_wrapper.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
part 'sales_event.dart';
part 'sales_state.dart';
@ -50,7 +53,9 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
final int productId = event.productId;
log("Requesting purchase for: " + productId.toString());
Track().track(TrackingEvent.purchase_request);
try {
final Product? selectedProduct = this.getSelectedProduct(productId);
log("SelectedProduct for purchase $selectedProduct");
if (selectedProduct != null) {
await RevenueCatPurchases().makePurchase(selectedProduct);
@ -70,6 +75,25 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
} else {
emit(SalesError(message: "No selected product"));
}
} on PlatformException catch (e) {
await Sentry.captureException(e);
var errorCode = PurchasesErrorHelper.getErrorCode(e);
if (errorCode == PurchasesErrorCode.invalidReceiptError) {
log("iOS Sandbox invalid receipt");
Cache().hasPurchased = true;
log(" -- Purchased -- ");
return;
}
log(e.toString());
if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
emit(SalesError(message: "Purchase was cancelled"));
} else {
emit(SalesError(message: "Purchase was not successful"));
}
} on Exception catch (e) {
log(e.toString());
emit(SalesError(message: "Purchase was not successful"));
}
}
Future<void> init() async {
@ -161,10 +185,10 @@ class SalesBloc extends Bloc<SalesEvent, SalesState> with Logging {
return;
}
String productSetString = splitTestRepository.getSplitTestValue("product_set_5");
log("ProductSetString: $productSetString");
//String productSetString = splitTestRepository.getSplitTestValue("product_set_5");
//log("ProductSetString: $productSetString");
try {
productSet = int.parse(productSetString);
productSet = 5;
} on Exception catch (e) {
log("Define the right productset! $e");
productSet = 2;

View File

@ -7,6 +7,7 @@ import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/util/session.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:upgrader/upgrader.dart';
part 'session_event.dart';
part 'session_state.dart';
@ -24,13 +25,22 @@ class SessionBloc extends Bloc<SessionEvent, SessionState> with Logging {
log(" -------- Session starting...");
emit(SessionLoading());
try {
this.settingsBloc = event.settingsBloc;
await session.fetchSessionAndNavigate();
FirebaseApi().setupRemoteConfig();
String lang = AppLanguage().appLocal.languageCode;
log("Change lang to $lang");
settingsBloc!.add(SettingsChangeLanguage(language: lang));
final iTunes = ITunesSearchAPI();
final resultsFuture = iTunes.lookupByBundleId('com.aitrainer.app');
resultsFuture.then((results) {
print('iTunes results: $results');
});
emit(SessionReady());
} on Exception catch (e) {
emit(SessionFailure(message: e.toString()));
}
}
@override

View File

@ -1,4 +1,4 @@
import 'package:aitrainer_app/main.dart';
import 'package:flutter/foundation.dart';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
@ -61,7 +61,7 @@ class TestSetNewBloc extends Bloc<TestSetNewEvent, TestSetNewState> {
exerciseRepository.end = DateTime.now();
await exerciseRepository.addExercise();
executeBloc.add(TestSetExecuteExerciseFinished(exerciseTypeId: exerciseType.exerciseTypeId, quantity: quantity, unitQuantity: unitQuantity));
if (!isInDebugMode) {
if (kReleaseMode) {
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = Cache().userLoggedIn;
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);

View File

@ -17,7 +17,7 @@ class TrainingEvaluationBloc extends Bloc<TrainingEvaluationEvent, TrainingEvalu
final String day;
TrainingEvaluationBloc({required this.trainingPlanBloc, required this.day}) : super(TrainingEvaluationInitial()) {
_load();
//on<TrainingEvaluationLoad>(_onLoad);
on<TrainingEvaluationLoad>(_onLoad);
}
String duration = "-";

View File

@ -1,6 +1,5 @@
import 'dart:collection';
import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/customer_training_plan.dart';
@ -23,6 +22,7 @@ import 'package:aitrainer_app/widgets/exercise_save.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
part 'training_plan_event.dart';
part 'training_plan_state.dart';
@ -174,7 +174,7 @@ class TrainingPlanBloc extends Bloc<TrainingPlanEvent, TrainingPlanState> with C
await Cache().saveMyTrainingPlan();
}
if (!isInDebugMode) {
if (kReleaseMode) {
CustomerRepository customerRepository = CustomerRepository();
customerRepository.customer = Cache().userLoggedIn;
MauticRepository mauticRepository = MauticRepository(customerRepository: customerRepository);

View File

@ -1,5 +1,5 @@
import 'dart:io';
//import 'dart:io';
/*
import 'package:sqflite/sqflite.dart';
class DB {
@ -35,3 +35,4 @@ class DB {
Database getDB() => this._db;
}
*/

View File

@ -145,7 +145,7 @@ class _AnimatedButtonState extends State<AnimatedButton> {
_AnimatedButtonState({
this.type,
this.color,
this.shadowColor,
//this.shadowColor,
this.borderColor,
this.blurColor,
});
@ -159,14 +159,14 @@ class _AnimatedButtonState extends State<AnimatedButton> {
int index = type!.index;
setState(() {
color = definedColors[index]["color"];
shadowColor = definedColors[index]["shadowColor"];
//shadowColor = definedColors[index]["shadowColor"];
blurColor = definedColors[index]["blurColor"];
borderColor = definedColors[index]["borderColor"];
});
} else {
setState(() {
color = widget.color;
shadowColor = widget.shadowColor;
//shadowColor = widget.shadowColor;
blurColor = widget.blurColor;
borderColor = widget.borderColor;
});

View File

@ -40,20 +40,13 @@ class ImageCache with Logging {
final String imageKey = generateMd5(url + "_" + id.toString());
// get from storage
final String imageString = (await getImageAs64BaseString(id, url))!;
final String? imageString = await getImageAs64BaseString(id, url);
if (imageString != null) {
_images[imageKey] = imageString;
_imageMap[imageKey] = true;
/* final String imageString = await getImageAs64BaseString(id, url);
if (imageString != null) {
_imageMap[imageKey] = imageString;
_imageDown[imageKey] = true;
}
}
_images[imageKey] = imageString;
_imageMap[imageKey] = true; */
}
Future<void> saveImageToPrefs(String key, String value) async {
//log(" save the key " + key);
@ -102,14 +95,14 @@ class ImageCache with Logging {
return image;
}
Future<String?> getImageAs64BaseString(int id, String name) async {
Future<String?>? getImageAs64BaseString(int id, String name) async {
final String imageKey = generateMd5(name + "_" + id.toString());
String? imageString;
if (await storage.containsKey(key: imageKey)) {
//log(" .. get from storage");
imageString = await storage.read(key: imageKey);
} else {
imageString = (await downloadAndSaveImage(id, name))!;
imageString = await downloadAndSaveImage(id, name);
//log(" .. downloaded");
}
return imageString;

View File

@ -1,7 +1,6 @@
library network_image_to_byte;
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';

View File

@ -76,7 +76,7 @@ class __TreeViewDataState extends State<_TreeViewData> {
super.initState();
/// 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;
subscription = stream.listen((value) {
if (value) {

View File

@ -1,5 +1,3 @@
// ignore_for_file: must_be_immutable
import 'dart:async';
import 'dart:io';
import 'package:aitrainer_app/bloc/test_set_execute/test_set_execute_bloc.dart';
@ -48,17 +46,17 @@ import 'package:aitrainer_app/widgets/development_diagram.dart';
import 'package:aitrainer_app/widgets/home.dart';
import 'package:aitrainer_app/library/facebook_app_events/facebook_app_events.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
//import 'package:flurry_data/flurry_data.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:aitrainer_app/util/app_localization.dart';
//import 'package:flutter_uxcam/flutter_uxcam.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
//import 'package:flutter_smartlook/flutter_smartlook.dart';
import 'package:flutter/foundation.dart';
import 'package:posthog_session/posthog_session.dart';
import 'package:upgrader/upgrader.dart';
import 'bloc/account/account_bloc.dart';
import 'bloc/body_development/body_development_bloc.dart';
@ -72,18 +70,7 @@ import 'model/cache.dart';
import 'view/training_evaluation_page.dart';
import 'package:syncfusion_localizations/syncfusion_localizations.dart';
const dsn = 'https://0f635b7225564abc9089f8106f25eb5c@sentry.aitrainer.app/1';
/// Whether the VM is running in debug mode.
///
/// This is useful to decide whether a report should be sent to sentry. Usually
/// reports from dev mode are not very useful, as these happen on developers'
/// workspaces rather than on users' devices in production.
bool get isInDebugMode {
bool inDebugMode = false;
assert(inDebugMode = true);
return inDebugMode;
}
const dsn = 'https://2309523cf2374c089fa1143d19209bc1@glitch.workouttest.org/2';
/// Reports [error] along with its [stackTrace] to Sentry.io.
Future<Null> _reportError(dynamic error, dynamic stackTrace) async {
@ -92,38 +79,51 @@ Future<Null> _reportError(dynamic error, dynamic stackTrace) async {
// Errors thrown in development mode are unlikely to be interesting. You can
// check if you are running in dev mode using an assertion and omit sending
// the report.
if (isInDebugMode) {
if (!kReleaseMode) {
print(stackTrace);
print('In dev mode. Not sending report to Sentry.io.');
return;
}
print('Reporting to Sentry.io...');
final String customerId = Cache().userLoggedIn != null ? Cache().userLoggedIn!.customerId.toString() : "0";
Sentry.configureScope(
(scope) => scope.user = SentryUser(id: customerId),
);
final String platform = Platform.isAndroid ? "Android" : "iOS";
final String version = Cache().packageInfo != null ? Cache().packageInfo!.version + "+" + Cache().packageInfo!.buildNumber : "";
final sentryId =
await Sentry.captureException(error, stackTrace: stackTrace, hint: "Platform: $platform, Version: $version, User: $customerId");
final sentryId = await Sentry.captureException(error, stackTrace: stackTrace);
print('Capture exception result : SentryId : $sentryId');
MatomoTracker.instance.trackEvent(eventCategory: "error", action: error.toString());
print('Track error to Matomo');
}
Future<Null> main() async {
// This captures errors reported by the Flutter framework.
FlutterError.onError = (FlutterErrorDetails details) async {
if (isInDebugMode) {
if (!kReleaseMode) {
// In development mode simply print to console.
FlutterError.dumpErrorToConsole(details);
} else {
//} else {
// In production mode report to the application zone to report to
// Sentry.
Zone.current.handleUncaughtError(details.exception, details.stack!);
}
};
Future<void> initThirdParty() async {
if (kReleaseMode) {
await MatomoTracker.instance.initialize(
siteId: 3,
url: 'https://matomo.workouttest.org/matomo.php',
);
}
Posthog().setContext({
'token':'v1.1.26'
});
Posthog().identify(userId: 0, properties: {
'token':'v1.1.26'
});
print(" -- FireBase init..");
await FirebaseApi().initializeFlutterFire();
}
// This creates a [Zone] that contains the Flutter application and stablishes
// an error handler that captures errors and reports them.
//
@ -136,43 +136,14 @@ Future<Null> main() async {
// - https://api.dartlang.org/stable/1.24.2/dart-async/Zone-class.html
// - https://www.dartlang.org/articles/libraries/zones
runZonedGuarded<Future<Null>>(() async {
if (!isInDebugMode) {
await SentryFlutter.init(
(options) {
options.dsn = dsn;
options.release = Cache().packageInfo != null ? Cache().packageInfo!.version + "+" + Cache().packageInfo!.buildNumber : "";
options.enableAutoSessionTracking = true;
},
);
}
Future<void> initThirdParty() async {
if (!isInDebugMode) {
//await FlurryData.initialize(androidKey: "JNYCTCWBT34FM3J8TV36", iosKey: "3QBG7BSMGPDH24S8TRQP", enableLog: true);
await MatomoTracker.instance.initialize(
siteId: 3,
url: 'https://matomo.workouttest.com/matomo.php',
//visitorId: 'customer_1',
);
//FlutterUxcam.optIntoSchematicRecordings();
}
await FirebaseApi().initializeFlutterFire();
}
final WorkoutTreeRepository menuTreeRepository = WorkoutTreeRepository();
WidgetsFlutterBinding.ensureInitialized();
if (!isInDebugMode) {
//FlutterUxcam.startWithKey("wvdstyoml4tiwfd");
//SetupOptions options = (new SetupOptionsBuilder('682883e5cd71a46160c4f6ed070530ee593f49c6')).build();
//Smartlook.setupAndStartRecording(options);
//Smartlook.setEventTrackingMode(EventTrackingMode.FULL_TRACKING);
}
await initThirdParty();
final FirebaseAnalytics analytics = FirebaseAnalytics.instance;
print(" -- FireBase init..");
runApp(MultiBlocProvider(
await SentryFlutter.init((options) => options..dsn = dsn,
appRunner: () => runApp(MultiBlocProvider(
providers: [
BlocProvider<SessionBloc>(
create: (BuildContext context) => SessionBloc(session: Session()),
@ -209,7 +180,7 @@ Future<Null> main() async {
}),
],
child: WorkoutTestApp(analytics: analytics),
));
)));
}, (error, stackTrace) async {
await _reportError(error, stackTrace);
});
@ -227,7 +198,7 @@ class WorkoutTestApp extends StatelessWidget {
Upgrader().installAppStoreListingURL(Platform.isAndroid
? "https://play.google.com/store/apps/details?id=com.aitrainer.aitrainer_app"
: "https://apps.apple.com/hu/app/workouttest/id1515271425");
//Upgrader().installAppStoreVersion("1.1.19");
Upgrader().installAppStoreVersion("1.1.26");
// On iOS, the default behavior will be to use the App Store version of
// the app, so update the Bundle Identifier in example/ios/Runner with a
// valid identifier already in the App Store.
@ -305,13 +276,12 @@ class WorkoutTestApp extends StatelessWidget {
title: 'WorkoutTest',
theme: ThemeData(
brightness: Brightness.light,
//primarySwatch: Colors.transparent,
//fontFamily: 'Arial',
textTheme: TextTheme(
bodyText1: GoogleFonts.inter(textStyle: TextStyle(fontSize: 14.0)),
)),
navigatorObservers: [
FirebaseAnalyticsObserver(analytics: analytics),
PosthogObserver(),
],
home: AitrainerHome(),
);

View File

@ -1,5 +1,6 @@
import 'dart:collection';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:aitrainer_app/model/customer.dart';
import 'package:aitrainer_app/model/customer_activity.dart';
import 'package:aitrainer_app/model/customer_property.dart';
@ -27,20 +28,17 @@ import 'package:aitrainer_app/repository/customer_repository.dart';
import 'package:aitrainer_app/service/firebase_api.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/package_service.dart';
import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/env.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:firebase_remote_config/firebase_remote_config.dart';
//import 'package:flurry_data/flurry_data.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
//import 'package:flutter_uxcam/flutter_uxcam.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:package_info/package_info.dart';
import 'package:posthog_session/posthog_session.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:aitrainer_app/model/exercise_type.dart';
import 'package:intl/intl.dart';
//import 'package:flutter_smartlook/flutter_smartlook.dart';
import 'customer_exercise_device.dart';
import 'exercise_device.dart';
@ -117,10 +115,10 @@ class Cache with Logging {
static final String activeExercisePlanDetailsKey = "active_exercise_details_plan";
static final String myTrainingPlanKey = "myTrainingPlan";
static String baseUrlLive = 'https://aitrainer.info:8943/api/';
static String baseUrlTest = 'https://aitrainer.info:8843/api/';
static String baseUrlLive = 'https://api.workouttest.org/api/';
static String baseUrlTest = 'https://apitest.workouttest.org/api/';
late String baseUrl;
static final String mediaUrl = 'https://admin.aitrainer.app/media/';
static final String mediaUrl = 'https://admin.workouttest.org/media/';
static final String username = 'bosi';
static final String password = 'andio2009';
@ -214,6 +212,12 @@ class Cache with Logging {
return this.authToken;
}
Future<void> deleteCustomerId(int customerId) async {
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
SharedPreferences sharedPreferences = await prefs;
sharedPreferences.remove(Cache.customerIdKey);
}
Future<void> saveActiveExercisePlan(ExercisePlan exercisePlan, List<ExercisePlanDetail> exercisePlanDetails) async {
this.activeExercisePlan = exercisePlan;
this.activeExercisePlanDetails = exercisePlanDetails;
@ -695,15 +699,17 @@ class Cache with Logging {
return;
}
if (!isInDebugMode) {
if (kReleaseMode) {
//FlurryData.setUserId(customerId.toString());
//FlutterUxcam.setUserProperty("username", customerId.toString());
//FlutterUxcam.setUserIdentity(customerId.toString());
//Smartlook.setUserIdentifier(customerId.toString());
//Smartlook.instance.
Track().track(TrackingEvent.enter);
MatomoTracker.instance
.trackEvent(eventName: TrackingEvent.enter.enumToString(), eventCategory: "", action: TrackingEvent.enter.enumToString(), eventValue: customerId);
MatomoTracker.instance.setVisitorUserId(customerId.toString());
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: TrackingEvent.enter.enumToString());
Posthog().identify(userId: customerId.toString());
Posthog().capture(eventName: TrackingEvent.enter.enumToString());
}
await Future.forEach(ActivityDone.values, (element) async {

View File

@ -94,7 +94,7 @@ class CustomerTrainingPlanDetails {
this.exerciseType = Cache().getExerciseTypeById(exerciseTypeId!);
this.baseOneRepMax = json['baseOneRepMax'];
this.baseOneRepMax = json['baseOneRepMax'] == null ? 0 : json['baseOneRepMax'];
}
ExerciseType? getExerciseType() => exerciseType;

View File

@ -23,7 +23,7 @@ class CustomerRepository with Logging {
Customer? _trainee;
List<Customer>? _trainees;
List<CustomerProperty>? _properties;
List<CustomerProperty>? _allCustomerProperties;
//List<CustomerProperty>? _allCustomerProperties;
final PropertyRepository propertyRepository = PropertyRepository();
final List<Property> womanSizes = [];
final List<Property> manSizes = [];
@ -45,7 +45,7 @@ class CustomerRepository with Logging {
isMan = (Cache().userLoggedIn!.sex == "m");
}
_allCustomerProperties = Cache().getCustomerPropertyAll();
//_allCustomerProperties = Cache().getCustomerPropertyAll();
}
String? getGenderByName(String name) {

View File

@ -204,7 +204,7 @@ class UserRepository with Logging {
Future<void> getUser() async {
final User modelUser = this.user;
String rc = await FirebaseApi().signInEmail(modelUser.email, modelUser.password);
try {
if (rc == FirebaseApi.SIGN_IN_OK) {
await CustomerApi().getUserByEmail(modelUser.email!);
await Cache().afterFirebaseLogin();
@ -212,6 +212,9 @@ class UserRepository with Logging {
log("Exception: user not found or password is wrong");
throw Exception("Customer does not exist or the password is wrong");
}
} on NotFoundException catch (_) {
throw Exception("Customer does not exist or the password is wrong");
}
}
Future<void> resetPassword() async {

View File

@ -5,6 +5,7 @@ import 'package:aitrainer_app/util/common.dart';
import 'package:aitrainer_app/util/not_found_exception.dart';
import 'package:flutter/services.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
class APIClient with Common, Logging {
static final APIClient _singleton = APIClient._internal();
@ -45,12 +46,18 @@ class APIClient with Common, Logging {
HttpClientResponse result = await request.close();
client.close();
if (result.statusCode != 200) {
trace("authentication response: ${result.statusCode}");
throw Exception("Network error, try again later!");
trace("authentication response: ${result.statusCode} with URL: $url");
throw Exception("Authentication error: ${result.statusCode}");
}
return jsonDecode(await result.transform(utf8.decoder).join());
} catch (exception) {
print(exception.toString());
try {
await Sentry.captureException(exception);
} on Exception catch (e) {
print(e);
}
throw Exception("Network error, try again later!");
}
}
@ -85,15 +92,18 @@ class APIClient with Common, Logging {
} else {
throw Exception("Network Error, please try again later");
}
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) {
print("Post Exception: $e");
await Sentry.captureException(e);
throw Exception("Network Error, please try again later");
}
}
Future<String> get(String endPoint, String param) async {
final url = Cache().getBaseUrl() + endPoint + param;
try {
trace("-------- API get " + url);
String authToken = Cache().getAuthToken();
if (authToken.length == 0) {
@ -120,5 +130,12 @@ class APIClient with Common, Logging {
} else {
throw Exception("Network Error, please try again later");
}
} on NotFoundException catch(e) {
throw NotFoundException(message: "Not Found");
} on Exception catch (e) {
print("Post Exception: $e");
await Sentry.captureException(e);
throw Exception("Network Error, please try again later");
}
}
}

View File

@ -32,6 +32,11 @@ class CustomerApi with Logging {
await _client.post("customers/update_firebase_uid/" + customerId.toString(), uid);
}
Future<void> deactivateCustomer(int customerId) async {
log(" ===== deactivate : $customerId");
await _client.post("customers/deactivate/$customerId", "");
}
Future<void> addCustomer(Customer customer) async {
customer.dateAdd = DateTime.now();
customer.dateChange = DateTime.now();

View File

@ -2,7 +2,8 @@ import 'dart:math' as math;
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/service/logging.dart' as logging;
import 'package:aitrainer_app/service/logging.dart' as logger;
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
@ -11,7 +12,7 @@ import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter_facebook_auth/flutter_facebook_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class FirebaseApi with logging.Logging {
class FirebaseApi with logger.Logging {
bool appleSignInAvailable = false;
static final FirebaseAuth auth = FirebaseAuth.instance;
@ -37,25 +38,6 @@ class FirebaseApi with logging.Logging {
this.appleSignInAvailable = await SignInWithApple.isAvailable();
/* AwesomeNotifications().initialize(
// set the icon to null if you want to use the default app icon
null,
[
NotificationChannel(
channelKey: 'basic_channel',
channelName: 'Basic notifications',
channelDescription: 'Notification channel for basic tests',
defaultColor: Color(0xFF9D50DD),
ledColor: Colors.white)
]);
AwesomeNotifications().isNotificationAllowed().then((isAllowed) {
if (!isAllowed) {
// Insert here your friendly dialog box before call the request method
// This is very important to not harm the user experience
AwesomeNotifications().requestPermissionToSendNotifications();
}
}); */
await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
alert: true, // Required to display a heads up notification
@ -75,9 +57,9 @@ class FirebaseApi with logging.Logging {
print('Message also contained a notification: ${message.notification}');
}
});
} catch (e) {
// Set `_error` state to true if Firebase initialization fails
Sentry.captureException(e);
log("Error initializing Firebase");
}
}
@ -94,6 +76,7 @@ class FirebaseApi with logging.Logging {
userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password);
Cache().firebaseUid = userCredential.user!.uid;
} on FirebaseAuthException catch (e) {
Sentry.captureException(e);
if (e.code == 'user-not-found') {
log('No user found for that email.');
rc = SIGN_IN_NOT_FOUND;
@ -113,6 +96,7 @@ class FirebaseApi with logging.Logging {
userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword(email: email, password: password);
Cache().firebaseUid = userCredential.user!.uid;
} on FirebaseAuthException catch (e) {
Sentry.captureException(e);
if (e.code == 'weak-password') {
log('The password provided is too weak.');
rc = REGISTER_WEAK_PWD;
@ -124,6 +108,7 @@ class FirebaseApi with logging.Logging {
}
} catch (e) {
log(e.toString());
Sentry.captureException(e);
throw Exception(e.toString());
}
return rc;
@ -145,26 +130,6 @@ class FirebaseApi with logging.Logging {
Future<Map<String, dynamic>> signInWithApple() async {
Map<String, dynamic> userData = Map();
/* final apple.AuthorizationResult result = await SignInWithApple.performRequests([
apple.AppleIdRequest(requestedScopes: [apple.Scope.email, apple.Scope.fullName])
]);
switch (result.status) {
case apple.AuthorizationStatus.authorized:
print('User authorized');
break;
case apple.AuthorizationStatus.error:
print('User error');
throw Exception("Apple Sign-In failed");
case apple.AuthorizationStatus.cancelled:
print('User cancelled');
throw Exception("Apple Sign-In cancelled");
}
// Create an `OAuthCredential` from the credential returned by Apple.
final oauthCredential = OAuthProvider("apple.com").credential(
idToken: String.fromCharCodes(result.credential.identityToken),
accessToken: String.fromCharCodes(result.credential.authorizationCode!));
*/
// To prevent replay attacks with the credential returned from Apple, we
// include a nonce in the credential request. When signing in with
// Firebase, the nonce in the id token returned by Apple, is expected to
@ -186,9 +151,15 @@ class FirebaseApi with logging.Logging {
idToken: appleCredential.identityToken,
rawNonce: rawNonce,
);
UserCredential? userCredential;
try {
// Sign in the user with Firebase. If the nonce we generated earlier does
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
} on FirebaseAuthException catch(e) {
Sentry.captureException(e);
throw Exception(e);
}
Cache().firebaseUid = userCredential.user!.uid;
log("userCredential: " + userCredential.toString());
@ -200,21 +171,7 @@ class FirebaseApi with logging.Logging {
Future<Map<String, dynamic>> registerWithApple() async {
Map<String, dynamic> userData = Map();
/* final apple.AuthorizationResult result = await apple.TheAppleSignIn.performRequests([
apple.AppleIdRequest(requestedScopes: [apple.Scope.email, apple.Scope.fullName])
]);
switch (result.status) {
case apple.AuthorizationStatus.authorized:
print('Apple User authorized');
break;
case apple.AuthorizationStatus.error:
print('Apple User error');
throw Exception("Apple Sign-In failed");
case apple.AuthorizationStatus.cancelled:
print('User cancelled');
throw Exception("Apple Sign-In cancelled");
}
*/
final rawNonce = generateNonce();
final nonce = sha256ofString(rawNonce);
@ -232,14 +189,15 @@ class FirebaseApi with logging.Logging {
rawNonce: rawNonce,
);
/* // Create an `OAuthCredential` from the credential returned by Apple.
final oauthCredential = OAuthProvider("apple.com").credential(
idToken: String.fromCharCodes(result.credential.identityToken),
accessToken: String.fromCharCodes(result.credential.authorizationCode));
*/
UserCredential? userCredential;
try {
// Sign in the user with Firebase. If the nonce we generated earlier does
// not match the nonce in `appleCredential.identityToken`, sign in will fail.
UserCredential userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
userCredential = await FirebaseAuth.instance.signInWithCredential(oauthCredential);
} on FirebaseAuthException catch(e) {
Sentry.captureException(e);
throw Exception(e);
}
Cache().firebaseUid = userCredential.user!.uid;
@ -261,6 +219,7 @@ class FirebaseApi with logging.Logging {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
Sentry.captureException(new Exception("Google Sign In failed"));
throw Exception("Google Sign In failed");
}
@ -297,6 +256,7 @@ class FirebaseApi with logging.Logging {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
if (googleUser == null) {
Sentry.captureException(new Exception("Google Sign In failed"));
throw Exception("Google Sign In failed");
}
@ -333,6 +293,7 @@ class FirebaseApi with logging.Logging {
Cache().firebaseUid = userData['id'];
log(userData.toString());
} else {
Sentry.captureException(new Exception(result.message));
throw Exception("Facebook login was not successful");
}
@ -360,6 +321,7 @@ class FirebaseApi with logging.Logging {
Cache().firebaseUid = userCredential.user!.uid;
} else {
Sentry.captureException(new Exception(result.message));
throw Exception("Facebook login was not successful");
}
@ -381,11 +343,10 @@ class FirebaseApi with logging.Logging {
Future<void> setupRemoteConfig() async {
//initializeFlutterFire();
RemoteConfig? remoteConfig;
FirebaseRemoteConfig? remoteConfig;
try {
remoteConfig = RemoteConfig.instance;
await remoteConfig.setConfigSettings(
RemoteConfigSettings(
remoteConfig = FirebaseRemoteConfig.instance;
await remoteConfig.setConfigSettings(RemoteConfigSettings(
fetchTimeout: const Duration(seconds: 10),
minimumFetchInterval: const Duration(seconds: 1),
));

View File

@ -4,7 +4,7 @@ import 'package:aitrainer_app/model/mautic.dart';
import 'package:aitrainer_app/service/logging.dart';
class MauticApi with Logging {
final String mauticUrl = "https://mautic.aitrainer.app/form/submit?formId=";
final String mauticUrl = "https://mautic.workouttest.org/form/submit?formId=";
Future<void> sendMauticForm(Mautic model) async {
final String body = model.toForm();

View File

@ -145,6 +145,21 @@ mixin Common {
return average;
}
double getRepeatByOneRepMax(double oneRepMax, double weight) {
double repeats = ( 80 * oneRepMax - 80 * weight ) / ( weight * ( 40 * 0.0333 + 1) );
//print("getRepeatsByOneRepMax: $repeats");
return repeats;
}
int calculateRepeatBy1RMPercent(double oneRepMax, double weight, double percent) {
return getRepeatByOneRepMax(oneRepMax , weight * percent).round();
}
double calculate1RMPercentByRepeat(double oneRepMax, double weight, double repeat) {
double percent = 80 * oneRepMax / (weight * ( repeat * ( 40 * 0.0333 + 1 ) + 80));
return percent;
}
static double get1RMPercent(int repeats) {
double percent = 1;
@ -231,3 +246,5 @@ mixin Common {
return list;
}
}
class CommonHoldingClass with Common {}

View File

@ -53,6 +53,7 @@ enum TrackingEvent {
tutorial_activate,
terms_of_use,
data_privacy,
delete_account,
faq,
training_plan_open,
training_plan_start,
@ -60,7 +61,7 @@ enum TrackingEvent {
training_plan_finished,
training_plan_custom,
trial,
feedback_email
feedback_email,
}
T enumFromString<T>(Iterable<T> values, String value) {

View File

@ -50,6 +50,7 @@ class RevenueCatPurchases with Logging {
log("Trial mode: $inTrial date: ${Cache().userLoggedIn!.trialDate}");
if (Cache().userLoggedIn!.admin == 1 || inTrial || Cache().userLoggedIn!.lifeLong == 1) {
Cache().hasPurchased = true;
log(" -- Purchased -- ");
}
}
@ -74,7 +75,6 @@ class RevenueCatPurchases with Logging {
}
Future<void> makePurchase(wtproduct.Product product) async {
try {
if (_offering == null) {
_offering = await getOfferings();
}
@ -94,27 +94,15 @@ class RevenueCatPurchases with Logging {
PurchaserInfo purchaserInfo = await Purchases.purchasePackage(selectedPackage);
if (purchaserInfo.entitlements.all["wt_subscription"] != null && purchaserInfo.entitlements.all["wt_subscription"]!.isActive) {
Cache().hasPurchased = true;
log(" -- Purchased -- ");
}
} else {
log("!!!! No Selected package to purchase");
throw Exception("Purchase was not successful");
throw Exception("No Selected package to purchase");
}
} else {
log("!!!! No active offering");
}
} on PlatformException catch (e) {
var errorCode = PurchasesErrorHelper.getErrorCode(e);
if (errorCode == PurchasesErrorCode.invalidReceiptError) {
log("iOS Sandbox invalid receipt");
Cache().hasPurchased = true;
return;
}
log(e.toString());
if (errorCode == PurchasesErrorCode.purchaseCancelledError) {
throw Exception("Purchase was cancelled");
} else {
throw Exception("Purchase was not successful");
}
throw Exception("No active offering");
}
}
}

View File

@ -1,4 +1,3 @@
import 'package:aitrainer_app/main.dart';
import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/service/logging.dart';
import 'package:aitrainer_app/service/tracking_service.dart';
@ -6,10 +5,9 @@ import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/model/tracking.dart' as model;
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
//import 'package:flurry_data/flurry_data.dart';
//import 'package:flutter_uxcam/flutter_uxcam.dart';
//import 'package:flutter_smartlook/flutter_smartlook.dart';
import 'package:posthog_session/posthog_session.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:flutter/foundation.dart';
class Track with Logging {
static final Track _singleton = Track._internal();
@ -22,12 +20,9 @@ class Track with Logging {
Track._internal();
void track(TrackingEvent event, {String eventValue = ""}) {
if (!isInDebugMode) {
//FlurryData.logEvent(event.enumToString());
//Smartlook.setGlobalEventProperty(event.toString(), eventValue, false);
//FlutterUxcam.logEventWithProperties(event.enumToString(), {"value": eventValue});
model.Tracking tracking = model.Tracking();
tracking.customerId = Cache().userLoggedIn == null ? 0 : Cache().userLoggedIn!.customerId!;
if (kReleaseMode) {
tracking.event = event.enumToString();
if (eventValue.isNotEmpty) {
tracking.eventValue = eventValue;
@ -38,7 +33,21 @@ class Track with Logging {
FirebaseMessaging.instance.subscribeToTopic(event.enumToString());
analytics.logEvent(name: event.enumToString(), parameters: {"value": eventValue});
MatomoTracker.instance.trackEvent(eventName: event.enumToString(), eventCategory: "", action: eventValue, eventValue: tracking.customerId);
}
if (eventValue.isNotEmpty) {
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: event.enumToString(), eventName: eventValue);
} else {
MatomoTracker.instance.trackEvent(eventCategory: "wt", action: event.enumToString());
}
Posthog().capture(
eventName: event.enumToString(),
properties: {
'eventValue': eventValue,
'customer': tracking.customerId,
},
);
}
}
}

View File

@ -14,6 +14,9 @@ import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
import '../util/enums.dart';
import '../util/track.dart';
// ignore: must_be_immutable
class AccountPage extends StatelessWidget with Trans {
// ignore: close_sinks
@ -73,7 +76,7 @@ class AccountPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
if (Cache().userLoggedIn != null)
@ -94,7 +97,7 @@ class AccountPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
if (Cache().userLoggedIn != null)
@ -116,7 +119,7 @@ class AccountPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
if (Cache().userLoggedIn != null)
@ -134,7 +137,7 @@ class AccountPage extends StatelessWidget with Trans {
title: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t(bodyType), style: TextStyle(color: Colors.blue)),
@ -152,6 +155,9 @@ class AccountPage extends StatelessWidget with Trans {
),
devices(context, accountBloc),
loginOut(context, accountBloc),
Divider(),
Divider(),
deleteAccount(accountBloc),
//messaging(),
//getMyTrainees(context, accountBloc),
]);
@ -165,7 +171,7 @@ class AccountPage extends StatelessWidget with Trans {
title: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t("Available Devices"), style: TextStyle(color: Colors.blue)),
@ -189,7 +195,7 @@ class AccountPage extends StatelessWidget with Trans {
title: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t("Trigger message"), style: TextStyle(color: Colors.purple)),
@ -218,7 +224,7 @@ class AccountPage extends StatelessWidget with Trans {
title: TextButton(
style: TextButton.styleFrom(
backgroundColor: Colors.white38,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t(text), style: TextStyle(color: buttonColor)),
@ -241,6 +247,29 @@ class AccountPage extends StatelessWidget with Trans {
return element;
}
ListTile deleteAccount(AccountBloc accountBloc) {
return ListTile(
leading: Icon(Icons.delete_forever),
title: TextButton(
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Text(t("Delete Account"), style: TextStyle(color: Color.fromARGB(255, 202, 10, 10))),
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
if (accountBloc.loggedIn)
{
deleteAccountConfirmationDialog(accountBloc),
}
},
),
);
}
Widget getMyTrainees(BuildContext context, AccountBloc accountBloc) {
if (accountBloc.customerRepository.customer == null || accountBloc.customerRepository.customer!.trainer == 0) {
return ListTile(
@ -253,7 +282,7 @@ class AccountPage extends StatelessWidget with Trans {
leading: Icon(Icons.people),
title: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.white70,
backgroundColor: Colors.white70,
),
onPressed: () => accountBloc.add(AccountGetTrainees()),
child: Text("See my trainees"),
@ -303,6 +332,35 @@ class AccountPage extends StatelessWidget with Trans {
));
}
void deleteAccountConfirmationDialog(AccountBloc accountBloc) {
showCupertinoDialog(
useRootNavigator: true,
context: context,
builder: (_) => CupertinoAlertDialog(
title: Text(t("Are you sure to delete your account?")),
content: Column(children: [
Divider(),
Text(t("Your training data, historical data, goals, 1RMs will be completly lost!")),
]),
actions: [
TextButton(
child: Text(t("No")),
onPressed: () => Navigator.pop(context),
),
TextButton(
child: Text(t("Yes")),
onPressed: () => {
if (accountBloc.customerRepository.customer != null && accountBloc.customerRepository.customer!.customerId != null) {
Track().track(TrackingEvent.delete_account),
accountBloc.add(DeleteAccount(customer: accountBloc.customerRepository.customer!)),
},
Navigator.pop(context),
},
)
],
));
}
void confirmationDialog(AccountBloc accountBloc) {
showCupertinoDialog(
useRootNavigator: true,

View File

@ -13,8 +13,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import '../bloc/customer_change/customer_change_bloc.dart';
// ignore: must_be_immutable
class CustomerFitnessPage extends StatefulWidget {
late _CustomerFitnessPageState _state;

View File

@ -11,8 +11,6 @@ import 'package:google_fonts/google_fonts.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import '../bloc/customer_change/customer_change_bloc.dart';
// ignore: must_be_immutable
class CustomerHeightPage extends StatefulWidget {
late _CustomerHeightPageState _state;

View File

@ -11,8 +11,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import '../bloc/customer_change/customer_change_bloc.dart';
// ignore: must_be_immutable
class CustomerSexPage extends StatefulWidget {
late _CustomerSexPageState _state;

View File

@ -11,8 +11,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
import '../bloc/customer_change/customer_change_bloc.dart';
// ignore: must_be_immutable
class CustomerWeightPage extends StatefulWidget {
late _CustomerWeightPageState _state;

View File

@ -59,10 +59,10 @@ class _CustomerWelcomePageState extends State<CustomerWelcomePage> with Trans {
duration: Duration(seconds: 6),
),
SizedBox(
height: 110,
height: 40,
),
CircularPercentIndicator(
radius: 250.0,
radius: 200.0,
animation: true,
animationDuration: 4800,
lineWidth: 20.0,

View File

@ -327,8 +327,8 @@ class _ExerciseControlPage extends State<ExerciseControlPage> with Trans {
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(0),
primary: Colors.white,
onSurface: Colors.blueAccent,
foregroundColor: Colors.white,
disabledForegroundColor: Colors.blueAccent,
),
onPressed: () {
exerciseBloc.add(ExerciseControlSubmit(step: step));

View File

@ -47,7 +47,7 @@ class _MyDevelopmentMuscleState extends State<MyDevelopmentMusclePage> with Comm
}
/// We require the initializers to run after the loading screen is rendered
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
BlocProvider.of<DevelopmentByMuscleBloc>(context).add(DevelopmentByMuscleLoad());
});
}

View File

@ -66,7 +66,10 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
text: t("My Training Logs"),
style: GoogleFonts.robotoMono(
textStyle: TextStyle(
fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4))),
fontSize: 14,
color: Colors.white,
fontWeight: FontWeight.bold,
backgroundColor: Colors.black54.withOpacity(0.4))),
image: "asset/image/edzesnaplom400400.jpg",
left: 5,
onTap: () => Navigator.of(context).pushNamed('mydevelopmentLog', arguments: args),
@ -186,7 +189,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
onTap: () => {Navigator.of(context).pushNamed('mydevelopmentMusclePage', arguments: args)},
isLocked: true,
))),
developmentWidget(imageWidth, t("Development of My Sizes"), "asset/image/sizes_q.jpg", TrackingEvent.my_size_development, args),
developmentWidget(
imageWidth, t("Development of My Sizes"), "asset/image/sizes_q.jpg", TrackingEvent.my_size_development, args),
hiddenWidget(customerRepository, exerciseRepository),
]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
@ -207,7 +211,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
textAlignment: Alignment.topLeft,
text: t(title),
style: GoogleFonts.robotoMono(
textStyle: TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4))),
textStyle:
TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.bold, backgroundColor: Colors.black54.withOpacity(0.4))),
image: imageUrl,
onTap: () => {
if (Cache().userLoggedIn != null)
@ -240,8 +245,8 @@ class _MyDevelopmentPage extends State<MyDevelopmentPage> with Trans {
return TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(20),
primary: Colors.white,
onSurface: Colors.blueAccent,
backgroundColor: Colors.white,
disabledForegroundColor: Colors.blueAccent,
),
onPressed: () => {
if (Cache().getTrainee() != null)

View File

@ -43,8 +43,8 @@ class SettingsPage extends StatelessWidget with Trans {
child: Form(
child: BlocConsumer<SettingsBloc, SettingsState>(listener: (context, state) {
if (state is SettingsError) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(backgroundColor: Colors.orange, content: Text(state.message, style: TextStyle(color: Colors.white))));
} else if (state is SettingsReady) {
menuBloc.add(MenuRecreateTree());
Navigator.of(context).pushNamed("home");
@ -193,7 +193,7 @@ class SettingsPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
Track().track(TrackingEvent.terms_of_use),
@ -220,7 +220,7 @@ class SettingsPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
Track().track(TrackingEvent.data_privacy),
@ -247,7 +247,7 @@ class SettingsPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
Navigator.of(context).pushNamed("faqPage"),
@ -290,7 +290,7 @@ class SettingsPage extends StatelessWidget with Trans {
]),
style: TextButton.styleFrom(
backgroundColor: Colors.white70,
onSurface: Colors.grey,
disabledForegroundColor: Colors.grey,
),
onPressed: () => {
launchMailto(),
@ -311,6 +311,7 @@ class SettingsPage extends StatelessWidget with Trans {
// Use either Dart's string interpolation
// or the toString() method.
print("Mailto: $mailtoLink");
await launch('$mailtoLink');
final Uri _url = Uri.parse("$mailtoLink");
await launchUrl(_url);
}
}

View File

@ -165,8 +165,8 @@ class TestSetControl extends StatelessWidget with Trans {
TextButton(
style: TextButton.styleFrom(
padding: EdgeInsets.all(0),
primary: Colors.white,
onSurface: Colors.blueAccent,
foregroundColor: Colors.white,
disabledForegroundColor: Colors.blueAccent,
),
onPressed: () => {
bloc.add(TestSetControlSubmit()),

View File

@ -316,8 +316,8 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
getPlanDetails(plan, bloc, dayName),
ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: restricted ? Colors.grey[600] : Colors.orange,
foregroundColor: Colors.white,
backgroundColor: restricted ? Colors.grey[600] : Colors.orange,
),
child: Text(t("Start")),
onPressed: () {
@ -476,7 +476,8 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
return DialogCommon(
title: t("Dropset"),
descriptions: t("A drop set is an advanced resistance training technique "),
description2: t(" in which you focus on completing a set until failure - or the inability to do another repetition."),
description2:
t(" in which you focus on completing a set until failure - or the inability to do another repetition."),
text: "OK",
onTap: () => {
Navigator.of(context).pop(),
@ -490,7 +491,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
headerGridLinesVisibility: GridLinesVisibility.both,
gridLinesVisibility: GridLinesVisibility.both,
columns: [
GridTextColumn(
GridColumn(
columnWidthMode: ColumnWidthMode.lastColumnFill,
maximumWidth: 130,
columnName: 'exerciseImage',
@ -507,7 +508,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
GridColumn(
maximumWidth: 0,
visible: false,
columnName: 'exerciseName',
@ -520,7 +521,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
GridColumn(
maximumWidth: 60,
columnName: 'Set',
label: Container(
@ -532,7 +533,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
GridColumn(
maximumWidth: 100,
columnWidthMode: ColumnWidthMode.fill,
columnName: 'Repeats',
@ -545,7 +546,7 @@ class TrainingPlanActivatePage extends StatelessWidget with Trans {
style: GoogleFonts.inter(color: Colors.white, fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
))),
GridTextColumn(
GridColumn(
maximumWidth: 60,
columnName: 'Weight',
label: Container(

View File

@ -297,7 +297,7 @@ class _ExerciseListState extends State<ExerciseList> with Trans {
@override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
animate();
});
super.initState();
@ -306,7 +306,7 @@ class _ExerciseListState extends State<ExerciseList> with Trans {
@override
void didUpdateWidget(ExerciseList page) {
super.didUpdateWidget(page);
WidgetsBinding.instance!.addPostFrameCallback((_) {
WidgetsBinding.instance.addPostFrameCallback((_) {
animate();
});
}
@ -333,8 +333,8 @@ class _ExerciseListState extends State<ExerciseList> with Trans {
String description2 = "";
if (next.exerciseTypeId != detail.exerciseTypeId) {
title = AppLocalizations.of(context)!.translate("Stop!");
description =
AppLocalizations.of(context)!.translate("Please continue with the next exercise in the queue:") + next.exerciseType!.nameTranslation;
description = AppLocalizations.of(context)!.translate("Please continue with the next exercise in the queue:") +
next.exerciseType!.nameTranslation;
} else {
final HashMap args = HashMap();
args['exerciseType'] = next.exerciseType;
@ -388,7 +388,8 @@ class _ExerciseListState extends State<ExerciseList> with Trans {
bloc.getMyPlan()!.days[widget.dayName]!.forEach((element) {
if (prev == null || (prev != null && prev!.exerciseTypeId != element.exerciseTypeId)) {
tiles.add(GestureDetector(
onTap: () => bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
onTap: () =>
bloc.getNext() != null ? executeExercise(bloc, bloc.getNext()!, context) : Navigator.of(context).pushNamed('home'),
child: ExerciseTile(
bloc: bloc,
detail: element,
@ -543,7 +544,8 @@ class ExerciseTile extends StatelessWidget with Trans {
List<Widget> getExerciseTiles(CustomerTrainingPlanDetails detail) {
final List<Widget> list = [];
if (bloc.alternatives[detail.customerTrainingPlanDetailsId] != null && bloc.alternatives[detail.customerTrainingPlanDetailsId].length > 0) {
if (bloc.alternatives[detail.customerTrainingPlanDetailsId] != null &&
bloc.alternatives[detail.customerTrainingPlanDetailsId].length > 0) {
int index = 0;
for (CustomerTrainingPlanDetails alternative in bloc.alternatives[detail.customerTrainingPlanDetailsId]) {
final Widget widget = getTile(alternative, index);
@ -563,7 +565,10 @@ class ExerciseTile extends StatelessWidget with Trans {
final int step = bloc.getStep(detail);
final int highlightStep = bloc.getHighlightStep(detail);
final bool hasLeftAlternative = detail.alternatives.length > 0 && index > 0;
final bool hasRightAlternative = detail.alternatives.length > 0 && index + 1 < bloc.alternatives[detail.customerTrainingPlanDetailsId].length;
final bool hasRightAlternative =
detail.alternatives.length > 0 && index + 1 < bloc.alternatives[detail.customerTrainingPlanDetailsId].length;
print("getTile Detail: $detail");
return Container(
child: Stack(alignment: Alignment.centerRight, children: [
@ -598,7 +603,8 @@ class ExerciseTile extends StatelessWidget with Trans {
context: context,
builder: (BuildContext context) {
return DialogHTML(
title: detail.exerciseType!.nameTranslation, htmlData: '<p>' + detail.exerciseType!.descriptionTranslation + '</p>');
title: detail.exerciseType!.nameTranslation,
htmlData: '<p>' + detail.exerciseType!.descriptionTranslation + '</p>');
}),
icon: Icon(
Icons.info_outline,

View File

@ -86,7 +86,7 @@ class MyTrainingPlans extends StatelessWidget with Trans, Logging {
getTrainingPlan(t("Training Plans of Celebrities"), "asset/menu/training_plans_q_celebrities.jpg", "celebrities"),
getTrainingPlan(t("Training Plans for Gain Strength"), "asset/menu/training_plans_q_gain_strength.jpg", "gain_strength"),
getTrainingPlan(t("Training Plans for Muscle Endurance"), "asset/menu/muscle_strength_q.jpg", "muscle_endurance"),
getTrainingPlan(t("Physical Prepare Program for Footgolfers"), "asset/menu/FG_2_edz.jpg", "footgolf"),
getTrainingPlan(t("12 Week Fit Boost Programm"), "asset/image/12w_fit_boost_q.jpg", "12w_fit_boost"),
]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,

View File

@ -38,7 +38,7 @@ class _BottomBarMultipleExercisesState extends State<BottomBarMultipleExercises>
@override
void initState() {
super.initState();
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
_controller = ScrollController();
});
}

View File

@ -209,12 +209,12 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
});
}
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
subscription = stream.listen((event) {
//_controller1.text = ExerciseSaveStream().weight.toStringAsFixed(0);
_controller2.text = ExerciseSaveStream().repeats.toStringAsFixed(0);
});
print("ExerciseSave weight ${widget.weight}");
//print("ExerciseSave weight ${widget.weight}");
_controller1.text = widget.weight == null || widget.weight == -1
? "TEST"
: widget.weight! % widget.weight!.round() == 0
@ -229,9 +229,11 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
: widget.repeats!.toStringAsFixed(0);
changable = (_controller2.text != "TEST" && _controller1.text != "TEST");
if (widget.unitQuantityUnit != null && widget.tip != null && Cache().isActivityDone(widget.tip!) == false) {
Timer(
/*Timer(
Duration(milliseconds: 2000),
() => {
if (context != null)
{
TutorialWidget().explanation(
context,
ExplanationWidget(
@ -241,7 +243,8 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
weight: widget.weight,
repeats: widget.repeats,
)),
});
}
});*/
}
});
}
@ -387,7 +390,7 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
leading: IconButton(
iconSize: 30,
onPressed: () => {
if (widget.unitQuantityUnit != null)
if (widget.unitQuantityUnit != null && context != null)
{
TutorialWidget().explanation(
context,
@ -633,7 +636,8 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
padding: const EdgeInsets.all(2),
color: Colors.white70,
onPressed: () async {
stopWatchTimer.onExecute.add(StopWatchExecute.start);
//stopWatchTimer.onExecute.add(StopWatchExecute.start);
stopWatchTimer.onStartTimer();
Wakelock.enable(); // prevent sleep the phone
},
icon: Icon(CustomIcon.play_1),
@ -647,7 +651,8 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
iconSize: 40,
color: Colors.white70,
onPressed: () async {
stopWatchTimer.onExecute.add(StopWatchExecute.stop);
//stopWatchTimer.onExecute.add(StopWatchExecute.stop);
stopWatchTimer.onStartTimer();
Wakelock.disable();
},
icon: Icon(CustomIcon.stop),
@ -660,7 +665,8 @@ class _ExerciseSaveState extends State<ExerciseSave> with Trans {
iconSize: 40,
color: Colors.white70,
onPressed: () async {
stopWatchTimer.onExecute.add(StopWatchExecute.reset);
//stopWatchTimer.onExecute.add(StopWatchExecute.reset);
stopWatchTimer.onResetTimer();
},
icon: Icon(CustomIcon.creative_commons_zero),
),

View File

@ -12,6 +12,7 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:matomo_tracker/matomo_tracker.dart';
import 'package:upgrader/upgrader.dart';
import 'loading.dart';
@ -25,15 +26,21 @@ class AitrainerHome extends StatefulWidget {
}
}
class _HomePageState extends State<AitrainerHome> with Logging, Trans {
class _HomePageState extends State<AitrainerHome> with Logging, Trans, TraceableClientMixin {
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
String get traceName => 'Home';
@override
String get traceTitle => this.widget.toString();
@override
void initState() {
super.initState();
/// We require the initializers to run after the loading screen is rendered
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
runDelayedEvent();
});
@ -65,12 +72,12 @@ class _HomePageState extends State<AitrainerHome> with Logging, Trans {
setContext(context);
final appcastURL = "https://raw.githubusercontent.com/bossanyit/appcast/main/android_rss.xml";
final cfg = AppcastConfiguration(url: appcastURL, supportedOS: ['android']);
print("Packageinfo ${Cache().packageInfo}");
return Scaffold(
key: _scaffoldKey,
body: UpgradeAlert(
upgrader: Upgrader(appcastConfig: cfg, messages: MyLocalizedUpgraderMessages(context: context)),
upgrader: Upgrader(
countryCode: AppLanguage().appLocal.toString(), appcastConfig: cfg, messages: MyLocalizedUpgraderMessages(context: context)),
child: BlocConsumer<SessionBloc, SessionState>(listener: (context, state) {
if (state is SessionFailure) {
showDialog(

View File

@ -174,8 +174,8 @@ class _InputDialogState<Event> extends State<InputDialog<Event>> with Trans {
children: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.black26,
onSurface: Colors.white,
backgroundColor: Colors.black26,
disabledBackgroundColor: Colors.white,
),
onPressed: () {
Navigator.of(context).pop();
@ -187,8 +187,8 @@ class _InputDialogState<Event> extends State<InputDialog<Event>> with Trans {
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.orange[600],
onSurface: Colors.white,
backgroundColor: Colors.orange[600],
disabledForegroundColor: Colors.white,
),
onPressed: () {
widget.onChanged(this.inputValue);

View File

@ -5,7 +5,6 @@ import 'package:aitrainer_app/bloc/menu/menu_bloc.dart';
import 'package:aitrainer_app/repository/training_plan_repository.dart';
import 'package:aitrainer_app/util/enums.dart';
import 'package:aitrainer_app/util/track.dart';
import 'package:aitrainer_app/widgets/dialog_trial.dart';
import 'package:aitrainer_app/widgets/menu_image.dart';
import 'package:aitrainer_app/widgets/menu_search_bar.dart';
import 'package:aitrainer_app/util/app_language.dart';
@ -55,7 +54,7 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
}
/// We require the initializers to run after the loading screen is rendered
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
menuBloc.add(MenuCreate());
});
@ -112,7 +111,9 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
return Stack(children: [
CustomScrollView(
controller: scrollController, scrollDirection: Axis.vertical, slivers: buildMenuColumn(widget.parent!, context, menuBloc, cWidth, cHeight)),
controller: scrollController,
scrollDirection: Axis.vertical,
slivers: buildMenuColumn(widget.parent!, context, menuBloc, cWidth, cHeight)),
]);
}
@ -134,7 +135,8 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
padding: EdgeInsets.only(top: 15.0),
child: Center(
child: Stack(alignment: Alignment.bottomLeft, children: [
Text(AppLocalizations.of(context)!.translate("All Exercises has been filtered out"), style: GoogleFonts.inter(color: Colors.white)),
Text(AppLocalizations.of(context)!.translate("All Exercises has been filtered out"),
style: GoogleFonts.inter(color: Colors.white)),
]))));
} else {
menuBloc.getFilteredBranch(menuBloc.parent).forEach((treeName, value) {
@ -395,8 +397,10 @@ class _MenuPageWidgetState extends State<MenuPageWidget> with Trans, Logging {
dynamic getShape(WorkoutMenuTree workoutTree) {
bool base = workoutTree.base;
dynamic returnCode = (base == true)
? RoundedRectangleBorder(side: BorderSide(width: 6, color: Colors.orangeAccent), borderRadius: BorderRadius.all(Radius.circular(24.0)))
: RoundedRectangleBorder(side: BorderSide(width: 1, color: Colors.transparent), borderRadius: BorderRadius.all(Radius.circular(8.0)));
? RoundedRectangleBorder(
side: BorderSide(width: 6, color: Colors.orangeAccent), borderRadius: BorderRadius.all(Radius.circular(24.0)))
: RoundedRectangleBorder(
side: BorderSide(width: 1, color: Colors.transparent), borderRadius: BorderRadius.all(Radius.circular(8.0)));
return returnCode;
}

View File

@ -178,7 +178,7 @@ class TutorialWidget with Trans, Logging {
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.transparent,
backgroundColor: Colors.transparent,
),
onPressed: () => {bloc.add(TutorialNext(text: bloc.checks[0]))},
child: Text("« " + t(bloc.checks[0]),
@ -186,7 +186,7 @@ class TutorialWidget with Trans, Logging {
),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.transparent,
backgroundColor: Colors.transparent,
),
onPressed: () => {bloc.add(TutorialNext(text: bloc.checks[1]))},
child: Text(t(bloc.checks[1]) + " »",
@ -196,7 +196,7 @@ class TutorialWidget with Trans, Logging {
)
: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.transparent,
backgroundColor: Colors.transparent,
),
onPressed: () => {
//tooltip!.rebuild(context),

View File

@ -16,7 +16,7 @@ class _VictoryConfettiState extends State<VictoryConfetti> {
@override
void initState() {
_controllerBottomCenter = ConfettiController(duration: const Duration(seconds: 2));
SchedulerBinding.instance!.addPostFrameCallback((_) {
SchedulerBinding.instance.addPostFrameCallback((_) {
Future.delayed(Duration(milliseconds: 500)).then((value) => _controllerBottomCenter.play());
});
super.initState();

View File

@ -176,6 +176,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.5"
clock:
dependency: transitive
description:
@ -574,12 +581,12 @@ packages:
source: hosted
version: "2.2.1"
flutter_launcher_icons:
dependency: "direct dev"
dependency: "direct main"
description:
name: flutter_launcher_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.2"
version: "0.10.0"
flutter_layout_grid:
dependency: transitive
description:
@ -811,7 +818,7 @@ packages:
name: json_annotation
url: "https://pub.dartlang.org"
source: hosted
version: "4.4.0"
version: "4.7.0"
keyboard_actions:
dependency: "direct main"
description:
@ -867,7 +874,7 @@ packages:
name: matomo_tracker
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
version: "1.6.0"
meta:
dependency: transitive
description:
@ -1092,6 +1099,15 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.0"
posthog_session:
dependency: "direct main"
description:
path: "."
ref: HEAD
resolved-ref: "0db36d398cc23a7bfab09e0ddb6773525a92107b"
url: "https://bossanyit@git.workouttest.org/bossanyit/posthog_session.git"
source: git
version: "0.0.1"
process:
dependency: transitive
description:
@ -1321,20 +1337,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.0"
sqflite:
dependency: "direct main"
description:
name: sqflite
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0+1"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
url: "https://pub.dartlang.org"
source: hosted
version: "2.3.0"
stack_trace:
dependency: transitive
description:
@ -1426,13 +1428,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "20.3.50"
synchronized:
dependency: transitive
description:
name: synchronized
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.0+2"
term_glyph:
dependency: transitive
description:
@ -1517,27 +1512,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
universal_platform:
dependency: transitive
description:
name: universal_platform
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0+1"
upgrader:
dependency: "direct main"
description:
name: upgrader
url: "https://pub.dartlang.org"
source: hosted
version: "4.8.1"
version: "4.11.1"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.6"
version: "6.1.5"
url_launcher_android:
dependency: transitive
description:
@ -1784,5 +1772,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=2.18.0-0 <3.0.0"
flutter: ">=3.3.0-0"
dart: ">=2.18.4 <3.0.0"
flutter: ">=3.0.0"

View File

@ -15,10 +15,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.1.26+107
version: 1.1.28+117
environment:
sdk: ">=2.12.0 <3.9.0"
sdk: ">=2.18.4 <3.0.0"
dependencies:
flutter:
@ -54,6 +54,7 @@ dependencies:
flutter_fancy_tree_view: ^0.5.1+1
flutter_facebook_auth: ^4.4.1+1
flutter_fadein: ^2.0.0
flutter_launcher_icons: ^0.10.0
flutter_lints: ^2.0.1
flutter_radar_chart: ^0.2.1
flutter_secure_storage: ^5.0.2
@ -67,19 +68,20 @@ dependencies:
keyboard_actions: ^3.4.0
mailto: ^2.0.0
matomo_tracker: ^1.5.0
matomo_tracker: ^1.6.0
mockito: ^5.3.2
modal_progress_hud_nsn: ^0.3.0
package_info: ^2.0.2
percent_indicator: ^4.0.0
#posthog_flutter: ^2.0.3
purchases_flutter: ^3.9.5
rainbow_color: ^2.0.1
sentry_flutter: ^6.13.0
sentry_flutter: ^6.9.1
sign_in_with_apple: ^4.1.0
sqflite: ^2.1.0+1
#sqflite: ^2.1.0+1
stop_watch_timer: ^2.0.0
syncfusion_flutter_gauges: ^20.3.50
@ -91,13 +93,14 @@ dependencies:
timeline_tile: ^2.0.0
toggle_switch: ^2.0.1
upgrader: ^4.8.1
upgrader: ^4.11.1
url_launcher: ^6.0.9
wakelock: ^0.6.2
web_browser: ^0.5.0
posthog_session:
git: https://bossanyit@git.workouttest.org/bossanyit/posthog_session.git
#fl_chart: ^0.50.0
#location: ^3.2.4
#flurry_data: ^0.0.1
@ -122,11 +125,10 @@ dev_dependencies:
intl: ^0.17.0
shared_preferences: ^2.0.5
flutter_launcher_icons: ^0.9.0
flutter_icons:
android: "launcher_icon"
image_path: "asset/icon/icon.png"
ios: true
# For information on the generic Dart part of this file, see the
@ -177,14 +179,19 @@ flutter:
- asset/image/WT_cup_victory400.png
- asset/image/WT_zold.jpg
- asset/image/12w_fit_boost_q.jpg
- asset/image/12w_fit_boost.jpg
- asset/image/alternatives_arrow.png
- asset/image/add_test.png
- asset/image/button_fb.png
- asset/image/button_apple.png
- asset/image/button_google.png
- asset/image/cardio_distance.jpg
- asset/image/cardio_time.jpg
- asset/image/Congrats_N1.jpg
- asset/image/continue.png
- asset/image/drop_set.png
- asset/image/lock.png
- asset/image/add_test.png
- asset/image/testemfejl400x400.jpg
- asset/image/izomcsop400400.jpg
- asset/image/edzesnaplom400400.jpg

View File

@ -1,10 +1,10 @@
import 'package:aitrainer_app/model/cache.dart';
/*import 'package:aitrainer_app/model/cache.dart';
import 'package:aitrainer_app/model/exercise_plan.dart';
import 'package:aitrainer_app/model/exercise_plan_detail.dart';
import 'package:aitrainer_app/model/model_change.dart';
import 'package:test/test.dart';
import 'mocks.dart';
import 'mocks.dart';*/
/*
main() {
late SimExercisePlanRepository _exercisePlanRepository;
late int _customerId;
@ -141,3 +141,5 @@ main() {
});
});
}
*/

66
test/onerepmax.dart Normal file
View File

@ -0,0 +1,66 @@
import 'package:aitrainer_app/util/common.dart';
import 'package:test/test.dart';
main() {
late CommonHoldingClass commonClass;
setUp(() {
commonClass = CommonHoldingClass();
});
group('OneRepMax', () {
test('test OneRepMax', () async {
double weight = 60.0;
double repeats = 10;
double oneRepMax = commonClass.calculate1RM(weight, repeats);
//print("1RM: $oneRepMax");
print("1RM 100%: 1");
int repeat95 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.95);
print("1RM 95%: $repeat95");
int repeat90 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.9);
print("1RM 90%: $repeat90");
int repeat85 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.85);
print("1RM 85%: $repeat85");
int repeat83 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.82);
print("1RM 82%: $repeat83");
int repeat80 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.8);
print("1RM 80%: $repeat80");
int repeat77 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.775);
print("1RM 77,5%: $repeat77");
int repeat75 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.75);
print("1RM 75%: $repeat75");
int repeat74 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.74);
print("1RM 74%: $repeat74");
int repeat71 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.71);
print("1RM 71%: $repeat71");
int repeat70 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.7);
print("1RM 70%: $repeat70");
int repeat68 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.685);
print("1RM 68,5%: $repeat68");
int repeat65 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.65);
print("1RM 65%: $repeat65");
int repeat62 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.628);
print("1RM 62,8%: $repeat62");
int repeat60 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.6);
print("1RM 60%: $repeat60");
int repeat59 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.59);
print("1RM 59%: $repeat59");
int repeat53 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.535);
print("1RM 53,5%: $repeat53");
int repeat50 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.5);
print("1RM 50%: $repeat50");
int repeat49 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.495);
print("1RM 49,5%: $repeat49");
int repeat46 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.46);
print("1RM 45%: $repeat46");
int repeat40 = commonClass.calculateRepeatBy1RMPercent(oneRepMax, oneRepMax, 0.405);
print("1RM 40,5%: $repeat40");
expect(repeat90, 4);
expect(repeat50, 34);
});
});
}

View File

@ -17,10 +17,11 @@ import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; */
import 'package:aitrainer_app/helper/database.dart';
import 'package:flutter_test/flutter_test.dart';
//import 'package:aitrainer_app/helper/database.dart';
//import 'package:flutter_test/flutter_test.dart';
//import 'package:mockito/mockito.dart';
/*
void main() {
group('SQFLite', () {
setUp(() async {
@ -39,3 +40,4 @@ void main() {
});
});
}
*/

View File

@ -6,7 +6,7 @@
// tree, read text, and verify that the values of widget properties are correct.
//import 'package:aitrainer_app/bloc/login_form_bloc.dart';
import 'package:aitrainer_app/helper/database.dart';
//import 'package:aitrainer_app/helper/database.dart';
import 'package:aitrainer_app/library_keys.dart';
import 'package:aitrainer_app/util/app_localization.dart';
import 'package:aitrainer_app/model/user.dart';
@ -52,7 +52,7 @@ void main() {
late MockCommon common;
setUp(() async {
await DB().initDb();
//await DB().initDb();
common = MockCommon();
loginWidget = MaterialApp(home: LoginPage(), localizationsDelegates: [

View File

@ -1,9 +1,10 @@
import 'package:aitrainer_app/model/customer.dart';
import '../../lib/helper/database.dart';
//import 'package:aitrainer_app/model/customer.dart';
//import '../../lib/helper/database.dart';
/*
class CustomerApi {
Future<void> addCustomer(Customer customer) async {
//print(" ===== add new customer: " + customer.toSQL().toString();
await DB().getDB().insert("customer", customer.toJson());
}
}
*/