diff --git a/android/app/agconnect-services.json b/android/app/agconnect-services.json index 66f04d15..91aad2c7 100644 --- a/android/app/agconnect-services.json +++ b/android/app/agconnect-services.json @@ -1 +1,74 @@ -{"agcgw":{"url":"connect-drcn.dbankcloud.cn","backurl":"connect-drcn.hispace.hicloud.com","websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn","websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"2640966000002322881","product_id":"736430079244816567","client_id":"563735388191982656","client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF","project_id":"736430079244816567","app_id":"116912301","api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI","package_name":"com.cloudsolutions.HMGPatientApp"},"oauth_client":{"client_id":"116912301","client_type":1},"app_info":{"app_id":"116912301","package_name":"com.cloudsolutions.HMGPatientApp"},"service":{"analytics":{"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drcn.cloud.huawei.com"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"CN","configuration_version":"3.0","appInfos":[{"package_name":"com.cloudsolutions.HMGPatientApp","client":{"app_id":"116912301"},"app_info":{"package_name":"com.cloudsolutions.HMGPatientApp","app_id":"116912301"},"oauth_client":{"client_type":1,"client_id":"116912301"}},{"package_name":"com.ejada.hmg","client":{"app_id":"102857389"},"app_info":{"package_name":"com.ejada.hmg","app_id":"102857389"},"oauth_client":{"client_type":1,"client_id":"102857389"}}]} \ No newline at end of file +{ + "agcgw":{ + "backurl":"connect-drcn.hispace.hicloud.com", + "url":"connect-drcn.dbankcloud.cn", + "websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com", + "websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn" + }, + "agcgw_all":{ + "CN":"connect-drcn.dbankcloud.cn", + "CN_back":"connect-drcn.hispace.hicloud.com", + "DE":"connect-dre.dbankcloud.cn", + "DE_back":"connect-dre.hispace.hicloud.com", + "RU":"connect-drru.dbankcloud.cn", + "RU_back":"connect-drru.hispace.hicloud.com", + "SG":"connect-dra.dbankcloud.cn", + "SG_back":"connect-dra.hispace.hicloud.com" + }, + "client":{ + "cp_id":"2640966000002322881", + "product_id":"736430079244816567", + "client_id":"563735388191982656", + "client_secret":"650C7C799812AFFD53A10C7756CF05FB9F215A7E49032ABA8EBF3E14B77535CF", + "project_id":"736430079244816567", + "app_id":"102857389", + "api_key":"CgB6e3x9DJzMgRCmnT6dyUEkp6UsIfddb6l3w0ZEXzeiRMHEFi3400Z5fJ5qaHneU0OrAI/JRpk+DMGVs3QpUxlI", + "package_name":"com.ejada.hmg" + }, + "oauth_client":{ + "client_id":"102857389", + "client_type":1 + }, + "app_info":{ + "app_id":"102857389", + "package_name":"com.ejada.hmg" + }, + "service":{ + "analytics":{ + "collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", + "collector_url_ru":"datacollector-drru.dt.hicloud.com,datacollector-drru.dt.dbankcloud.cn", + "collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn", + "collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn", + "collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn", + "resource_id":"p1", + "channel_id":"" + }, + "search":{ + "url":"https://search-drcn.cloud.huawei.com" + }, + "cloudstorage":{ + "storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn" + }, + "ml":{ + "mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn" + } + }, + "region":"CN", + "configuration_version":"3.0", + "appInfos":[ + { + "package_name":"com.ejada.hmg", + "client":{ + "app_id":"102857389" + }, + "app_info":{ + "package_name":"com.ejada.hmg", + "app_id":"102857389" + }, + "oauth_client":{ + "client_type":1, + "client_id":"102857389" + } + } + ] +} diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 13f778ff..e115ebef 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -19,7 +19,8 @@ if (keystorePropertiesFile.exists()) { } android { - namespace = "com.cloudsolutions.HMGPatientApp" +// namespace = "com.cloudsolutions.HMGPatientApp" + namespace = "com.ejada.hmg" compileSdk = 36 // Using NDK 26 for better compatibility with Zoom SDK native libraries // ndkVersion = "27.0.12077973" @@ -33,7 +34,8 @@ android { } defaultConfig { - applicationId = "com.cloudsolutions.HMGPatientApp" +// applicationId = "com.cloudsolutions.HMGPatientApp" + applicationId = "com.ejada.hmg" // minSdk = 24 minSdk = 29 targetSdk = 36 @@ -141,6 +143,10 @@ flutter { source = "../.." } +configurations.all { + exclude(group = "org.jetbrains.kotlin", module = "kotlin-android-extensions-runtime") +} + dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.1.20") implementation("com.google.firebase:firebase-messaging:24.1.2") diff --git a/android/app/google-services.json b/android/app/google-services.json index 49bf1ace..3707617c 100644 --- a/android/app/google-services.json +++ b/android/app/google-services.json @@ -3,45 +3,9 @@ "project_number": "815750722565", "firebase_url": "https://api-project-815750722565.firebaseio.com", "project_id": "api-project-815750722565", - "storage_bucket": "api-project-815750722565.firebasestorage.app" + "storage_bucket": "api-project-815750722565.appspot.com" }, "client": [ - { - "client_info": { - "mobilesdk_app_id": "1:815750722565:android:fa20b3a2401e08633c186c", - "android_client_info": { - "package_name": "com.cloudsolutions.HMGPatientApp" - } - }, - "oauth_client": [ - { - "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", - "client_type": 3 - } - ], - "api_key": [ - { - "current_key": "AIzaSyDZDeWcBlRE3YfJWYt_DCiToVnANfaj8qg" - } - ], - "services": { - "appinvite_service": { - "other_platform_oauth_client": [ - { - "client_id": "815750722565-3a0gc7neins0eoahdrimrfksk0sqice8.apps.googleusercontent.com", - "client_type": 3 - }, - { - "client_id": "815750722565-0cq9366orvsk5ipivq6lijcj56u03fr7.apps.googleusercontent.com", - "client_type": 2, - "ios_info": { - "bundle_id": "com.void.demo" - } - } - ] - } - } - }, { "client_info": { "mobilesdk_app_id": "1:815750722565:android:62281cd3e5df4063", diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 70a68707..b6188224 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + package="com.ejada.hmg"> + + + + + + + + Gradle Configuration Cache + + + +
+ +
+ Loading... +
+ + + + + + diff --git a/android/gradle.properties b/android/gradle.properties index 210295ee..0e253cc0 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -3,9 +3,16 @@ android.enableR8=true android.enableR8.fullMode=true android.enableJetifier=true android.useDeprecatedNdk=true -org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureondemand=true android.useAndroidX=true android.enableImpeller=false +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false + +# Enabled parallel sync for Gradle 9.4+ +org.gradle.tooling.parallel=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 2299155e..4ee62d8f 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists #distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 1c91fb7c..434a4219 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -16,14 +16,34 @@ pluginManagement { } } +dependencyResolutionManagement { +// repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + repositoriesMode.set(RepositoriesMode.PREFER_PROJECT) + repositories { + google() + mavenCentral() + maven { + url = uri("https://storage.googleapis.com/download.flutter.io") + } + // Huawei HMS repo + maven { + url = uri("https://developer.huawei.com/repo/") + } + // Mapbox repo + maven { + url = uri("https://api.mapbox.com/downloads/v2/releases/maven") + } + } +} + plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" // id("com.android.application") version "8.9.3" apply false // START: FlutterFire Configuration id("com.google.gms.google-services") version("4.4.1") apply false // END: FlutterFire Configuration - id("com.android.application") version "8.9.3" apply false - id("org.jetbrains.kotlin.android") version "2.1.0" apply false + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false } include(":app") diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 51cc0ec3..f0e3c730 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -1533,6 +1533,7 @@ "vatPercent": "ضريبة القيمة المضافة (15%)", "proceedToPayment": "المتابعة للدفع", "supportedSmartWatches": "كيف تعمل؟", + "smartwatchHowItWorks": "كيف تعمل الساعة الذكية", "pleaseMakeSureSamsungWatchConnected": "يرجى التأكد من أن ساعة Samsung الخاصة بك متصلة بهاتفك، ومتزامنة ومحدثة بشكل نشط.", "beforeSyncingDataFollowInstructions": "قبل مزامنة البيانات، يرجى التأكد من اتباع التعليمات بشكل صحيح.", "viewWatchInstructions": "عرض تعليمات الساعة", @@ -1544,6 +1545,18 @@ "seconds": "ثواني", "secs": "ثواني", "noAllergiesDataFound": "لم يتم العثور على بيانات الحساسية...", + "allHealthData": "جميع البيانات الصحية", + "activityCalories": "سعرات النشاط", + "activityCaloriesDescription": "توفر حلقات النشاط مرجعًا بصريًا سريعًا لمدى نشاطك خلال كل يوم.", + "steps": "الخطوات", + "distanceCovered": "المسافة المقطوعة", + "distanceCoveredDescription": "المسافة المقطوعة على مدار اليوم", + "sleepScore": "مؤشر النوم", + "sleepScoreDescription": "يتتبع هذا عدد ساعات نومك خلال اليوم", + "bloodOxygen": "أكسجين الدم", + "bloodOxygenTrackingDescription": "يتتبع هذا مستوى أكسجين الدم لمراقبة السجل الصحي وتحديثه", + "bodyTemperature": "درجة حرارة الجسم", + "bodyTemperatureTrackingDescription": "يتتبع هذا درجة حرارة الجسم لمراقبة السجل الصحي وتحديثه", "heartRateDescription": "معدل ضربات قلبك يشير إلى عدد المرات التي ينبض فيها قلبك في الدقيقة", "bloodOxygenDescription": "مستوى الأكسجين في الدم يشير إلى كمية الأكسجين التي تحملها خلايا الدم الحمراء", "stepsDescription": "عدد الخطوات المتخذة على مدار اليوم", diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 4cf2827c..06a2742c 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -1526,6 +1526,7 @@ "vatPercent": "VAT (15%)", "proceedToPayment": "Proceed to Payment", "supportedSmartWatches": "Supported Smart Watches", + "smartwatchHowItWorks": "How does it work", "pleaseMakeSureSamsungWatchConnected": "Please make sure that your Samsung Watch is connected to your Phone, is actively synced & updated.", "beforeSyncingDataFollowInstructions": "Before syncing data, please make sure that you have followed the instructions properly.", "viewWatchInstructions": "View watch instructions", @@ -1537,6 +1538,18 @@ "seconds": "Seconds", "secs": "Secs", "noAllergiesDataFound": "No allergies data found...", + "allHealthData": "All Health Data", + "activityCalories": "Activity Calories", + "activityCaloriesDescription": "Activity rings give you a quick visual reference of how active you are each day.", + "steps": "Steps", + "distanceCovered": "Distance Covered", + "distanceCoveredDescription": "Distance covered throughout the day", + "sleepScore": "Sleep Score", + "sleepScoreDescription": "This keeps track of how many hours you sleep in a day", + "bloodOxygen": "Blood Oxygen", + "bloodOxygenTrackingDescription": "This tracks your blood oxygen to monitor and update your health history", + "bodyTemperature": "Body Temperature", + "bodyTemperatureTrackingDescription": "This tracks your body temperature to monitor and update your health history", "heartRateDescription": "Your heart rate indicates how many times your heart beats per minute", "bloodOxygenDescription": "Blood oxygen level indicates how much oxygen your red blood cells are carrying", "stepsDescription": "Number of steps taken throughout the day", diff --git a/ios/GoogleService-Info.plist b/ios/GoogleService-Info.plist index a9b1f53a..633037cb 100644 --- a/ios/GoogleService-Info.plist +++ b/ios/GoogleService-Info.plist @@ -2,6 +2,10 @@ + CLIENT_ID + 815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt ANDROID_CLIENT_ID 815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com API_KEY @@ -11,11 +15,11 @@ PLIST_VERSION 1 BUNDLE_ID - com.cloudsolutions.HMGPatientApp + com.HMG.HMG-Smartphone PROJECT_ID api-project-815750722565 STORAGE_BUCKET - api-project-815750722565.firebasestorage.app + api-project-815750722565.appspot.com IS_ADS_ENABLED IS_ANALYTICS_ENABLED @@ -27,7 +31,7 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:815750722565:ios:34ec03c09e02e21f3c186c + 1:815750722565:ios:328ec247a81a2ca23c186c DATABASE_URL https://api-project-815750722565.firebaseio.com diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index dac5fbe9..c0d2bb74 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,15 +3,15 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 37D27FAF2C38AC83B852680C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 478CFA942E638C8E0064F3D7 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */; }; + 5D5A1F80D389375644C4D0DC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56E413AB2A2E9765749CACD1 /* Pods_Runner.framework */; }; 61243B492EC5FA3700D46FA0 /* PenguinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */; }; 61243B4C2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */; }; 61243B502EC5FA3700D46FA0 /* PenguinView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61243B452EC5FA3700D46FA0 /* PenguinView.swift */; }; @@ -26,10 +26,10 @@ 76B1D2542F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 76B1D2552F91BF8000DBBD1B /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */; }; 76B1D2562F91BF8000DBBD1B /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -56,18 +56,27 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + 76B714E4300E58B2004DE37A /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 05E1B2A0E6844572ADA81174 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 3EAE1F31D8D0AA94CA6C11EB /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 56E413AB2A2E9765749CACD1 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 61243B3D2EC5FA3700D46FA0 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = ""; }; 61243B422EC5FA3700D46FA0 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = ""; }; 61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = ""; }; @@ -81,8 +90,10 @@ 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = ""; }; 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = ""; }; 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = ""; }; + 76B714CF300E58B1004DE37A /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; + 76B714D1300E58B1004DE37A /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7BEF44ABFEF585D64D3F266C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -90,8 +101,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; + BCE5BC40273DCC009E2FACB7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + C6416282AC56269448D7DA99 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + C6FD350374F47AFA34911C58 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,7 +115,7 @@ 76B1D2512F91BF8000DBBD1B /* Penguin.xcframework in Frameworks */, 76B1D2552F91BF8000DBBD1B /* PenNavUI.xcframework in Frameworks */, 76B1D2532F91BF8000DBBD1B /* PenguinINRenderer.xcframework in Frameworks */, - 37D27FAF2C38AC83B852680C /* Pods_Runner.framework in Frameworks */, + 5D5A1F80D389375644C4D0DC /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -144,7 +156,9 @@ 76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */, 76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */, 76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */, - A83C76CFF9D3F92EDE3B22B4 /* Pods_Runner.framework */, + 76B714CF300E58B1004DE37A /* WidgetKit.framework */, + 76B714D1300E58B1004DE37A /* SwiftUI.framework */, + 56E413AB2A2E9765749CACD1 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -152,9 +166,9 @@ 79DD2093A1D9674C94359FC8 /* Pods */ = { isa = PBXGroup; children = ( - 3EAE1F31D8D0AA94CA6C11EB /* Pods-Runner.debug.xcconfig */, - 05E1B2A0E6844572ADA81174 /* Pods-Runner.release.xcconfig */, - 7BEF44ABFEF585D64D3F266C /* Pods-Runner.profile.xcconfig */, + BCE5BC40273DCC009E2FACB7 /* Pods-Runner.debug.xcconfig */, + C6416282AC56269448D7DA99 /* Pods-Runner.release.xcconfig */, + C6FD350374F47AFA34911C58 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -234,27 +248,28 @@ productType = "com.apple.product-type.bundle.unit-test"; }; 97C146ED1CF9000F007C117D /* Runner */ = { - packageProductDependencies = ( - 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, - ); isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - EA10FC42B68E41E75A052FAA /* [CP] Check Pods Manifest.lock */, + 511FFA76807DE636962DBF91 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 765A5A922F35CD8B0003FF7D /* Embed Frameworks */, + 76B714E4300E58B2004DE37A /* Embed Foundation Extensions */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 5D78F615DF2D966539B34DE2 /* [CP] Embed Pods Frameworks */, - 4AA9AE39AD56A64A1F16E548 /* [CP] Copy Pods Resources */, + C7E5B2C65EE0A4D64ECC826B /* [CP] Embed Pods Frameworks */, + DF2C78ED8C8F648520DF8C43 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -263,12 +278,10 @@ /* Begin PBXProject section */ 97C146E61CF9000F007C117D /* Project object */ = { - packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, - ); isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 2610; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -291,6 +304,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -339,77 +355,77 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; - 4AA9AE39AD56A64A1F16E548 /* [CP] Copy Pods Resources */ = { + 511FFA76807DE636962DBF91 /* [CP] Check Pods Manifest.lock */ = { 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"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 5D78F615DF2D966539B34DE2 /* [CP] Embed Pods Frameworks */ = { + 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + inputPaths = ( ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + name = "Run Script"; + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + C7E5B2C65EE0A4D64ECC826B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputPaths = ( + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "Run Script"; - outputPaths = ( + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; }; - EA10FC42B68E41E75A052FAA /* [CP] Check Pods Manifest.lock */ = { + DF2C78ED8C8F648520DF8C43 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -511,7 +527,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -539,8 +555,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.0.12; - PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp; + MARKETING_VERSION = 4.6.044; + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -645,7 +661,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -696,7 +712,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -726,8 +742,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.0.12; - PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp; + MARKETING_VERSION = 4.6.044; + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -756,8 +772,8 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 0.0.12; - PRODUCT_BUNDLE_IDENTIFIER = com.cloudsolutions.HMGPatientApp; + MARKETING_VERSION = 4.6.044; + PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -800,12 +816,14 @@ defaultConfigurationName = Debug; }; /* End XCConfigurationList section */ + /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; /* End XCLocalSwiftPackageReference section */ + /* Begin XCSwiftPackageProductDependency section */ 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { isa = XCSwiftPackageProductDependency; diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..6cf27c0f --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,194 @@ +{ + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5", + "version" : "1.2024072200.0" + } + }, + { + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "3e33dd27dd4c69bd81c7c81fe61d8ccf58846902", + "version" : "11.3.1" + } + }, + { + "identity" : "dkcamera", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKCamera", + "state" : { + "branch" : "master", + "revision" : "5c691d11014b910aff69f960475d70e65d9dcc96" + } + }, + { + "identity" : "dkimagepickercontroller", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKImagePickerController", + "state" : { + "branch" : "4.3.9", + "revision" : "0bdfeacefa308545adde07bef86e349186335915" + } + }, + { + "identity" : "dkphotogallery", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKPhotoGallery", + "state" : { + "branch" : "master", + "revision" : "311c1bc7a94f1538f82773a79c84374b12a2ef3d" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "fdc352fabaf5916e7faa1f96ad02b1957e93e5a5", + "version" : "11.15.0" + } + }, + { + "identity" : "flutterfire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/flutterfire", + "state" : { + "revision" : "dadb0fd27bc9afe4dee4f23326a4a9ba238258ac", + "version" : "3.15.2-firebase-core-swift" + } + }, + { + "identity" : "google-ads-on-device-conversion-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk", + "state" : { + "revision" : "a2d0f1f1666de591eb1a811f40b1706f5c63a2ed", + "version" : "2.3.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "45ce435e9406d3c674dd249a042b932bee006f60", + "version" : "11.15.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "ba3358d3c3dbae8ef230b58a46b97ad65e84e974", + "version" : "10.1.1" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "9f183ae842be978784f2963a343682e0c46d8fb3", + "version" : "8.1.2" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6", + "version" : "1.69.1" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "c756a29784521063b6a1202907e2cc47f41b667c", + "version" : "4.5.0" + } + }, + { + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", + "version" : "101.0.0" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", + "version" : "1.22.5" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "3851d94a41890dea16dc3db34caf60e585cb4163", + "version" : "2.30910.1" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "f4a19a3c313dc2616c70bb49d29a799fb16be837", + "version" : "2.4.1" + } + }, + { + "identity" : "sdwebimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImage", + "state" : { + "revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0", + "version" : "5.21.7" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "55d7a1cc5666b85c13464aea1c4b4a90feccb4c8", + "version" : "1.38.1" + } + }, + { + "identity" : "swiftygif", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kirualex/SwiftyGif.git", + "state" : { + "revision" : "4430cbc148baa3907651d40562d96325426f409a", + "version" : "5.4.5" + } + }, + { + "identity" : "tocropviewcontroller", + "kind" : "remoteSourceControl", + "location" : "https://github.com/TimOliver/TOCropViewController", + "state" : { + "revision" : "d4a6d8100f4b886fdbc8ae399bf144ff3e9afb7e", + "version" : "2.8.0" + } + } + ], + "version" : 2 +} diff --git a/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..6cf27c0f --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,194 @@ +{ + "pins" : [ + { + "identity" : "abseil-cpp-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/abseil-cpp-binary.git", + "state" : { + "revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5", + "version" : "1.2024072200.0" + } + }, + { + "identity" : "app-check", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/app-check.git", + "state" : { + "revision" : "3e33dd27dd4c69bd81c7c81fe61d8ccf58846902", + "version" : "11.3.1" + } + }, + { + "identity" : "dkcamera", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKCamera", + "state" : { + "branch" : "master", + "revision" : "5c691d11014b910aff69f960475d70e65d9dcc96" + } + }, + { + "identity" : "dkimagepickercontroller", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKImagePickerController", + "state" : { + "branch" : "4.3.9", + "revision" : "0bdfeacefa308545adde07bef86e349186335915" + } + }, + { + "identity" : "dkphotogallery", + "kind" : "remoteSourceControl", + "location" : "https://github.com/zhangao0086/DKPhotoGallery", + "state" : { + "branch" : "master", + "revision" : "311c1bc7a94f1538f82773a79c84374b12a2ef3d" + } + }, + { + "identity" : "firebase-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/firebase-ios-sdk", + "state" : { + "revision" : "fdc352fabaf5916e7faa1f96ad02b1957e93e5a5", + "version" : "11.15.0" + } + }, + { + "identity" : "flutterfire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/flutterfire", + "state" : { + "revision" : "dadb0fd27bc9afe4dee4f23326a4a9ba238258ac", + "version" : "3.15.2-firebase-core-swift" + } + }, + { + "identity" : "google-ads-on-device-conversion-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk", + "state" : { + "revision" : "a2d0f1f1666de591eb1a811f40b1706f5c63a2ed", + "version" : "2.3.0" + } + }, + { + "identity" : "googleappmeasurement", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleAppMeasurement.git", + "state" : { + "revision" : "45ce435e9406d3c674dd249a042b932bee006f60", + "version" : "11.15.0" + } + }, + { + "identity" : "googledatatransport", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleDataTransport.git", + "state" : { + "revision" : "ba3358d3c3dbae8ef230b58a46b97ad65e84e974", + "version" : "10.1.1" + } + }, + { + "identity" : "googleutilities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/GoogleUtilities.git", + "state" : { + "revision" : "9f183ae842be978784f2963a343682e0c46d8fb3", + "version" : "8.1.2" + } + }, + { + "identity" : "grpc-binary", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/grpc-binary.git", + "state" : { + "revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6", + "version" : "1.69.1" + } + }, + { + "identity" : "gtm-session-fetcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/gtm-session-fetcher.git", + "state" : { + "revision" : "c756a29784521063b6a1202907e2cc47f41b667c", + "version" : "4.5.0" + } + }, + { + "identity" : "interop-ios-for-google-sdks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/interop-ios-for-google-sdks.git", + "state" : { + "revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe", + "version" : "101.0.0" + } + }, + { + "identity" : "leveldb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/leveldb.git", + "state" : { + "revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1", + "version" : "1.22.5" + } + }, + { + "identity" : "nanopb", + "kind" : "remoteSourceControl", + "location" : "https://github.com/firebase/nanopb.git", + "state" : { + "revision" : "3851d94a41890dea16dc3db34caf60e585cb4163", + "version" : "2.30910.1" + } + }, + { + "identity" : "promises", + "kind" : "remoteSourceControl", + "location" : "https://github.com/google/promises.git", + "state" : { + "revision" : "f4a19a3c313dc2616c70bb49d29a799fb16be837", + "version" : "2.4.1" + } + }, + { + "identity" : "sdwebimage", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SDWebImage/SDWebImage", + "state" : { + "revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0", + "version" : "5.21.7" + } + }, + { + "identity" : "swift-protobuf", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-protobuf.git", + "state" : { + "revision" : "55d7a1cc5666b85c13464aea1c4b4a90feccb4c8", + "version" : "1.38.1" + } + }, + { + "identity" : "swiftygif", + "kind" : "remoteSourceControl", + "location" : "https://github.com/kirualex/SwiftyGif.git", + "state" : { + "revision" : "4430cbc148baa3907651d40562d96325426f409a", + "version" : "5.4.5" + } + }, + { + "identity" : "tocropviewcontroller", + "kind" : "remoteSourceControl", + "location" : "https://github.com/TimOliver/TOCropViewController", + "state" : { + "revision" : "d4a6d8100f4b886fdbc8ae399bf144ff3e9afb7e", + "version" : "2.8.0" + } + } + ], + "version" : 2 +} diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index dc11bbed..8a0a6208 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -4,22 +4,58 @@ import FirebaseCore import FirebaseMessaging import GoogleMaps @main -@objc class AppDelegate: FlutterAppDelegate { +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + func didInitializeImplicitFlutterEngine(_ engineBridge: any FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + +// GMSServices.provideAPIKey("AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng") +// FirebaseApp.configure() +// initializePlatformChannels() + + } + override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GMSServices.provideAPIKey("AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng") - FirebaseApp.configure() +// FirebaseApp.configure() initializePlatformChannels() - GeneratedPluginRegistrant.register(with: self) +// GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } func initializePlatformChannels(){ - if let mainViewController = window?.rootViewController as? FlutterViewController{ // platform initialization suppose to be in foreground - HMGPenguinInPlatformBridge.initialize(flutterViewController: mainViewController) - } - } + + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + // 1. Try accessing window via AppDelegate (legacy/single-window setup) + var controller = self.window?.rootViewController as? FlutterViewController + + // 2. Fallback to UIWindowScene active window (modern iOS architecture) + if controller == nil { + controller = UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .flatMap { $0.windows } + .first(where: { $0.isKeyWindow })? + .rootViewController as? FlutterViewController + } + + // 3. Perform initialization once FlutterViewController is available + if let mainViewController = controller { + HMGPenguinInPlatformBridge.initialize(flutterViewController: mainViewController) + } else { + print("⚠️ FlutterViewController not ready yet for initializePlatformChannels.") + } + } + + +// if let mainViewController = window?.rootViewController as? FlutterViewController{ // platform initialization suppose to be in foreground +// HMGPenguinInPlatformBridge.initialize(flutterViewController: mainViewController) +// } + + } + override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken:Data){ // Messaging.messaging().apnsToken = deviceToken super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 65b74d7e..1eb27a20 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1 +1,128 @@ -{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file +{ + "images" : [ + { + "filename" : "Icon-App-20x20@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "Icon-App-20x20@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "Icon-App-29x29@1x.png", + "idiom" : "iphone", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "Icon-App-29x29@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "Icon-App-29x29@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "Icon-App-40x40@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "Icon-App-40x40@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "Icon-App-60x60@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "Icon-App-60x60@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "Icon-App-20x20@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "filename" : "Icon-App-20x20@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "Icon-App-29x29@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "filename" : "Icon-App-29x29@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "Icon-App-40x40@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "filename" : "Icon-App-40x40@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "Icon-App-76x76@1x.png", + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "filename" : "Icon-App-76x76@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "Icon-App-83.5x83.5@2x.png", + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "filename" : "icon.jpg", + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + }, + { + "filename" : "Icon-App-76x76@2x.png", + "idiom" : "iphone", + "scale" : "2x", + "size" : "76x76" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 0e65243a..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 2e4c7963..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 59435c76..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 20855aad..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index 11d35da4..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index 93523cbe..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 2e4c7963..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 00bb8dbd..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index 3eaa1fb6..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 3eaa1fb6..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index fd80aa41..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index 39c7958d..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 47a96a43..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 8c4ca7b0..00000000 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist index a9b1f53a..633037cb 100644 --- a/ios/Runner/GoogleService-Info.plist +++ b/ios/Runner/GoogleService-Info.plist @@ -2,6 +2,10 @@ + CLIENT_ID + 815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt ANDROID_CLIENT_ID 815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com API_KEY @@ -11,11 +15,11 @@ PLIST_VERSION 1 BUNDLE_ID - com.cloudsolutions.HMGPatientApp + com.HMG.HMG-Smartphone PROJECT_ID api-project-815750722565 STORAGE_BUCKET - api-project-815750722565.firebasestorage.app + api-project-815750722565.appspot.com IS_ADS_ENABLED IS_ANALYTICS_ENABLED @@ -27,7 +31,7 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:815750722565:ios:34ec03c09e02e21f3c186c + 1:815750722565:ios:328ec247a81a2ca23c186c DATABASE_URL https://api-project-815750722565.firebaseio.com diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index caa84333..85d84646 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -35,6 +35,7 @@ comgooglemaps baidumap iosamap + whatsapp LSRequiresIPhoneOS @@ -86,17 +87,38 @@ NSMicrophoneUsageDescription This app requires microphone access to enable virtual consultation between patient & doctor NSMotionUsageDescription - This app requires access to motion detection to count your daily steps. - NSPhotoLibraryUsageDescription - This app requires photo library access to select image as document & upload it. + This app requires motion detection access to function properly. NSPhotoLibraryAddUsageDescription This app requires photo library access to upload profile picture and documents. + NSPhotoLibraryUsageDescription + This app requires photo library access to select image as document & upload it. NSRemindersUsageDescription This app requires calendar access to set reminders for Virtual & Normal Appointments. NSSpeechRecognitionUsageDescription This app requires speech recognition access to access voice command features. NSUserActivityTypes + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + UIApplicationSupportsIndirectInputEvents UIBackgroundModes diff --git a/lib/core/api/api_client.dart b/lib/core/api/api_client.dart index 00eebb34..1bccb154 100644 --- a/lib/core/api/api_client.dart +++ b/lib/core/api/api_client.dart @@ -209,8 +209,8 @@ class ApiClientImp implements ApiClient { body['TokenID'] = "@dm!n"; } - body['TokenID'] = "@dm!n"; - // body['PatientID'] = 7000792; + // body['TokenID'] = "@dm!n"; + // body['PatientID'] = 1009156; // body['PatientID'] = 53320; // body['PatientTypeID'] = 1; // body['PatientOutSA'] = 0; @@ -223,9 +223,9 @@ class ApiClientImp implements ApiClient { // body['PatientID'] = 809289; } - if (!url.contains("/paymentApi")) { - body['IsNewFlutterApp'] = true; - } + // if (!url.contains("/paymentApi")) { + // body['IsNewFlutterApp'] = true; + // } body.removeWhere((key, value) => value == null); } diff --git a/lib/core/api_consts.dart b/lib/core/api_consts.dart index 6b54ff3d..3cac224b 100644 --- a/lib/core/api_consts.dart +++ b/lib/core/api_consts.dart @@ -316,8 +316,8 @@ class ApiConsts { static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations"; // ************ static values for Api **************** - static final double appVersionID = 22.4; - + // static final double appVersionID = 21.9; + static final double appVersionID = 21.5; // static final double appVersionID = 50.7; static final int appChannelId = 3; diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index c420a0c3..25753e1a 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -52,12 +52,12 @@ class AppState { // bool isMyFatoorahEnabled = true; void setIsPaytabsEnabled(bool value) { - isPaytabsEnabled = value; + isPaytabsEnabled = false; // isPaytabsEnabled = true; } void setIsMyFatoorahEnabled(bool value) { - isMyFatoorahEnabled = value; + isMyFatoorahEnabled = false; // isMyFatoorahEnabled = true; } @@ -70,7 +70,7 @@ class AppState { bool isChildLoggedIn = false; bool isGMSAvailable = true; bool isAndroid = true; - bool isRatedVisible =false; + bool isRatedVisible = false; void setAuthenticatedUser(AuthenticatedUser? authenticatedUser, {bool isFamily = false}) { if (isFamily) { _authenticatedChildUser = authenticatedUser; diff --git a/lib/core/talsec_config.dart b/lib/core/talsec_config.dart index 1603d419..d29d0dbb 100644 --- a/lib/core/talsec_config.dart +++ b/lib/core/talsec_config.dart @@ -2,12 +2,13 @@ import 'package:freerasp/freerasp.dart'; final talsecConfig = TalsecConfig( androidConfig: AndroidConfig( - packageName: 'com.cloudsolutions.HMGPatientApp', - signingCertHashes: ['6tvWaoN5coG4SnfxGbdQlcLmM0J4ePQwDjrKIg+QkV0=', 'j6VEqVhrypHMIiXiFdRLDdGwjGaMGWY7KAdBJA+Z4Pc='], // Must be the release cert hash + packageName: 'com.ejada.hmg', + signingCertHashes: ['6tvWaoN5coG4SnfxGbdQlcLmM0J4ePQwDjrKIg+QkV0=', 'j6VEqVhrypHMIiXiFdRLDdGwjGaMGWY7KAdBJA+Z4Pc=', 'EKw2Bd3VYz//DYjDnJLxEh3uGqhNDIWubLmpwAx/A7U='], // Must be the release cert hash supportedStores: ['com.android.vending'], // Google Play Store ), iosConfig: IOSConfig( - bundleIds: ['com.cloudsolutions.HMGPatientApp'], // iOS Bundle ID + // bundleIds: ['com.cloudsolutions.HMGPatientApp'], // iOS Bundle ID + bundleIds: ['com.HMG.HMG-Smartphone'], // iOS Bundle ID teamId: '3A359E86ZF', // Found in Apple Developer portal ), watcherMail: '', // Required to receive security alerts diff --git a/lib/core/utils/push_notification_handler.dart b/lib/core/utils/push_notification_handler.dart index 89f6969a..42d384c0 100644 --- a/lib/core/utils/push_notification_handler.dart +++ b/lib/core/utils/push_notification_handler.dart @@ -27,6 +27,7 @@ import 'package:hmg_patient_app_new/services/navigation_service.dart'; import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:uuid/uuid.dart'; +import 'package:huawei_push/huawei_push.dart' as h_push; // Global tracking variables for call state bool _isCallInProgress = false; @@ -425,10 +426,30 @@ class PushNotificationHandler { if (Platform.isAndroid) { try { - final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) { - log(err); - }); - if (fcmToken != null) onToken(fcmToken); + if (!(await Utils.isGoogleServicesAvailable())) { + h_push.Push.enableLogger(); + final result = await h_push.Push.setAutoInitEnabled(true); + + h_push.Push.onNotificationOpenedApp.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); + + h_push.Push.onMessageReceivedStream.listen((message) { + // newMessage(toFirebaseRemoteMessage(message)); + }, onError: (e) => print(e.toString())); + + h_push.Push.getTokenStream.listen((token) { + onToken(token); + }, onError: (e) => print(e.toString())); + h_push.Push.getToken(''); + + h_push.Push.registerBackgroundMessageHandler(backgroundMessageHandler); + } else { + final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) { + log(err); + }); + if (fcmToken != null) onToken(fcmToken); + } // } } catch (ex) { log("Notification Exception: $ex"); diff --git a/lib/features/authentication/authentication_view_model.dart b/lib/features/authentication/authentication_view_model.dart index 4436d269..e5324525 100644 --- a/lib/features/authentication/authentication_view_model.dart +++ b/lib/features/authentication/authentication_view_model.dart @@ -1421,7 +1421,8 @@ class AuthenticationViewModel extends ChangeNotifier { if (value) { LoaderBottomSheet.showLoader(); success(); - loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint); + // loginTypeEnum = (_appState.deviceTypeID == 1 ? LoginTypeEnum.face : LoginTypeEnum.fingerprint); + loginTypeEnum = (Platform.isIOS ? LoginTypeEnum.face : LoginTypeEnum.fingerprint); if (!_appState.isAuthenticated) { //commenting this api to check either the same flow working or not because this api does not needed further if work fine we will remove this await getPatientDeviceData(loginTypeEnum.toInt); diff --git a/lib/features/book_appointments/book_appointments_repo.dart b/lib/features/book_appointments/book_appointments_repo.dart index a705d84a..caf97cb8 100644 --- a/lib/features/book_appointments/book_appointments_repo.dart +++ b/lib/features/book_appointments/book_appointments_repo.dart @@ -37,7 +37,7 @@ abstract class BookAppointmentsRepo { Future>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare, {bool continueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError}); - Future>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}); + Future>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}); Future>> insertSpecificAppointment( {required int docID, @@ -483,12 +483,12 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo { } @override - Future> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}) async { + Future> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}) async { Map requestBody = { "AppointmentID": patientAppointmentHistoryResponseModel.appointmentNo, "ClinicID": patientAppointmentHistoryResponseModel.clinicID, "ProjectID": patientAppointmentHistoryResponseModel.projectID, - "CancelToReschadual": false, + "CancelToReschadual": isReschedule, "EndTime": patientAppointmentHistoryResponseModel.endTime, "StartTime": patientAppointmentHistoryResponseModel.startTime, "DoctorID": patientAppointmentHistoryResponseModel.doctorID, diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index a4530eee..5865a829 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -948,8 +948,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { ); } - Future cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async { - final result = await bookAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel); + Future cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await bookAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, isReschedule: isReschedule); result.fold( (failure) async => await errorHandlerService.handleError(failure: failure), @@ -1011,7 +1011,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { appointmentDate: apiResponse.data["SameClinicApptList"][0]['AppointmentDate'], ); - await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { + await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, isReschedule: true).then((val) async { // LoaderBottomSheet.hideLoader(); Future.delayed(Duration(milliseconds: 50)).then((value) async {}); // LoaderBottomSheet.showLoader(loadingText: LocaleKeys.bookingYourAppointment.tr()); @@ -1069,7 +1069,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { // loadingText: LocaleKeys.reschedulingAppo.tr(context: navigationService.navigatorKey.currentContext!), loadingText: LocaleKeys.loadingText.tr(context: navigationService.navigatorKey.currentContext!), ); - await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { + await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, isReschedule: true).then((val) async { LoaderBottomSheet.hideLoader(); Future.delayed(Duration(milliseconds: 50)).then((value) async {}); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.bookingYourAppointment.tr()); @@ -1174,7 +1174,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { isCloseButtonVisible: false, isDismissible: false, isFullScreen: false); - await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel).then((val) async { + await cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, isReschedule: true).then((val) async { navigationService.pop(); Future.delayed(Duration(milliseconds: 50)).then((value) async {}); LoaderBottomSheet.showLoader(loadingText: LocaleKeys.bookingYourAppointment.tr()); diff --git a/lib/features/my_appointments/my_appointments_repo.dart b/lib/features/my_appointments/my_appointments_repo.dart index 87fb2ec2..ef3cd283 100644 --- a/lib/features/my_appointments/my_appointments_repo.dart +++ b/lib/features/my_appointments/my_appointments_repo.dart @@ -44,7 +44,7 @@ abstract class MyAppointmentsRepo { Future>> generateAppointmentQR({required int clinicID, required int projectID, required String appointmentNo, required int isFollowUp}); - Future>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}); + Future>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}); Future>> confirmAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}); @@ -341,12 +341,12 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo { } @override - Future> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}) async { + Future> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}) async { Map requestBody = { "AppointmentID": patientAppointmentHistoryResponseModel.appointmentNo, "ClinicID": patientAppointmentHistoryResponseModel.clinicID, "ProjectID": patientAppointmentHistoryResponseModel.projectID, - "CancelToReschadual": false, + "CancelToReschadual": isReschedule, "EndTime": patientAppointmentHistoryResponseModel.endTime, "StartTime": patientAppointmentHistoryResponseModel.startTime, "DoctorID": patientAppointmentHistoryResponseModel.doctorID, diff --git a/lib/features/my_appointments/my_appointments_view_model.dart b/lib/features/my_appointments/my_appointments_view_model.dart index b2b990db..f040fd82 100644 --- a/lib/features/my_appointments/my_appointments_view_model.dart +++ b/lib/features/my_appointments/my_appointments_view_model.dart @@ -639,8 +639,8 @@ class MyAppointmentsViewModel extends ChangeNotifier { ); } - Future cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async { - final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel); + Future cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false, Function(dynamic)? onSuccess, Function(String)? onError}) async { + final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel, isReschedule: isReschedule); result.fold( // (failure) async => await errorHandlerService.handleError(failure: failure), diff --git a/lib/features/payfort/payfort_view_model.dart b/lib/features/payfort/payfort_view_model.dart index c4f96857..7b6b8b7d 100644 --- a/lib/features/payfort/payfort_view_model.dart +++ b/lib/features/payfort/payfort_view_model.dart @@ -578,4 +578,27 @@ class PayfortViewModel extends ChangeNotifier { ); } + Future addApplePayPayfortResponse(dynamic paymentMap) async { + PayfortResponseInsertModel payfortResponseInsertModel = PayfortResponseInsertModel(); + + payfortResponseInsertModel.fortId = paymentMap['fort_id'] ?? ""; + payfortResponseInsertModel.commandType = paymentMap['command'] ?? ""; + payfortResponseInsertModel.amount = num.tryParse(paymentMap['amount'] ?? "0") ?? 0; + payfortResponseInsertModel.sadadOLP = ""; + payfortResponseInsertModel.paymentOption = paymentMap['payment_option'] ?? ""; + payfortResponseInsertModel.customerIP = paymentMap['customer_ip'] ?? ""; + payfortResponseInsertModel.eCI = paymentMap['eci'] ?? ""; + payfortResponseInsertModel.responseMessage = paymentMap['response_message'] ?? ""; + payfortResponseInsertModel.cardNumber = paymentMap['card_number'] ?? ""; + payfortResponseInsertModel.cardBin = paymentMap['card_bin'] ?? ""; + payfortResponseInsertModel.installmentsNumber = int.tryParse(paymentMap['installments_number'] ?? "0") ?? 0; + payfortResponseInsertModel.status = paymentMap['status'] ?? ""; + payfortResponseInsertModel.merchantRef = paymentMap['merchant_reference'] ?? ""; + payfortResponseInsertModel.isRefund = false; + payfortResponseInsertModel.remmeberMe = true; + payfortResponseInsertModel.reconciliationReference = ""; + + payfortResponseInsert(payfortResponseInsertModel: payfortResponseInsertModel); + } + } diff --git a/lib/features/smartwatch_health_data/health_provider.dart b/lib/features/smartwatch_health_data/health_provider.dart index c296f717..1397703f 100644 --- a/lib/features/smartwatch_health_data/health_provider.dart +++ b/lib/features/smartwatch_health_data/health_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; import 'package:health/health.dart'; import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; import 'package:hmg_patient_app_new/core/common_models/smart_watch.dart'; @@ -119,15 +120,22 @@ class HealthProvider with ChangeNotifier { void initDevice() async { LoaderBottomSheet.showLoader(); notifyListeners(); + error = null; final result = await _healthService.initDevice(); isLoading = false; - LoaderBottomSheet.hideLoader(); + // LoaderBottomSheet.hideLoader(); if (result.isError) { - error = 'Error initializing device: ${result.asError}'; + LoaderBottomSheet.hideLoader(); + final rawError = result.asError?.error; + if (rawError is PlatformException) { + error = 'Error initializing device: ${rawError.message ?? rawError.toString()}'; + } else { + error = 'Error initializing device: ${rawError?.toString() ?? 'Unknown error'}'; + } } else { - LoaderBottomSheet.showLoader(); + // LoaderBottomSheet.showLoader(); await getVitals(); - // LoaderBottomSheet.hideLoader(); + LoaderBottomSheet.hideLoader(); // await Future.delayed(Duration(seconds: 5)); getIt.get().pushPage(page: SmartWatchesHealthDataScreen()); } @@ -286,4 +294,9 @@ class HealthProvider with ChangeNotifier { } return formattedString; } + + void clearError(){ + error = null; + notifyListeners(); + } } diff --git a/lib/features/smartwatch_health_data/model/vitals_data_model.dart b/lib/features/smartwatch_health_data/model/vitals_data_model.dart index 83cd4ea6..819e3773 100644 --- a/lib/features/smartwatch_health_data/model/vitals_data_model.dart +++ b/lib/features/smartwatch_health_data/model/vitals_data_model.dart @@ -22,6 +22,7 @@ class Vitals { if (timestamp.isEmpty) { timestamp = DateTime.now().toIso8601String(); } + timestamp = DateTime.parse(timestamp).toLocal().toIso8601String(); return Vitals( value: map['value'] ?? "", timestamp: timestamp, diff --git a/lib/features/smartwatch_health_data/watch_connectors/IllegalWatchTypeException.dart b/lib/features/smartwatch_health_data/watch_connectors/IllegalWatchTypeException.dart new file mode 100644 index 00000000..c3bfe4fc --- /dev/null +++ b/lib/features/smartwatch_health_data/watch_connectors/IllegalWatchTypeException.dart @@ -0,0 +1 @@ +class IllegalWatchTypeException implements Exception {} \ No newline at end of file diff --git a/lib/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart b/lib/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart index 8abb2136..2a4711b0 100644 --- a/lib/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart +++ b/lib/features/smartwatch_health_data/watch_connectors/create_watch_helper.dart @@ -6,6 +6,8 @@ import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connec import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/samsung_health.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart'; +import 'IllegalWatchTypeException.dart'; + class CreateWatchHelper { static WatchHelper getWatchName(SmartWatchTypes watchType) { /// if running device is ios @@ -16,7 +18,7 @@ class CreateWatchHelper { case SmartWatchTypes.huawei: return HuaweiHealthDataConnector(); default: - return SamsungHealth(); + throw IllegalWatchTypeException(); } } } \ No newline at end of file diff --git a/lib/features/smartwatch_health_data/watch_connectors/huawei_watch_connecter.dart b/lib/features/smartwatch_health_data/watch_connectors/huawei_watch_connecter.dart index a8300e2d..689bb517 100644 --- a/lib/features/smartwatch_health_data/watch_connectors/huawei_watch_connecter.dart +++ b/lib/features/smartwatch_health_data/watch_connectors/huawei_watch_connecter.dart @@ -1,86 +1,403 @@ import 'dart:async'; +import 'dart:convert'; import 'package:async/src/result/result.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; +import 'package:hmg_patient_app_new/features/smartwatch_health_data/model/vitals_data_model.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/watch_connectors/watch_helper.dart'; +import 'package:http/http.dart'; import 'package:huawei_health/huawei_health.dart'; + class HuaweiHealthDataConnector extends WatchHelper{ final MethodChannel _channel = MethodChannel('huawei_watch'); - @override - Future> initDevice() async{ - try{ - await _channel.invokeMethod('init'); - }catch(e){ + DataController? _dataController; + final Map> mappedData = >{}; + DateTime get _defaultEndDate => DateTime.now(); + DateTime get _defaultStartDate => _defaultEndDate.subtract(const Duration(days: 365)); + + @override + Future> initDevice() async { + try { + await _channel.invokeMethod('init'); + } catch (e) { + debugPrint('Huawei channel init failed: $e'); } - // List of scopes to ask for authorization. - // Note: These scopes should also be authorized on the Huawei Developer Console. - List scopes = [ - Scope.HEALTHKIT_STEP_READ, Scope.HEALTHKIT_OXYGEN_SATURATION_READ, // View and store height and weight data in Health Service Kit. - Scope.HEALTHKIT_HEARTRATE_READ, Scope.HEALTHKIT_SLEEP_READ, - Scope.HEALTHKIT_BODYTEMPERATURE_READ, Scope.HEALTHKIT_CALORIES_READ + + final List scopes = [ + Scope.HEALTHKIT_ACTIVITY_READ, + Scope.HEALTHKIT_ACTIVITY_WRITE, + Scope.HEALTHKIT_BLOODGLUCOSE_READ, + Scope.HEALTHKIT_BLOODGLUCOSE_WRITE, + Scope.HEALTHKIT_CALORIES_READ, + Scope.HEALTHKIT_CALORIES_WRITE, + Scope.HEALTHKIT_DISTANCE_READ, + Scope.HEALTHKIT_DISTANCE_WRITE, + Scope.HEALTHKIT_HEARTRATE_READ, + Scope.HEALTHKIT_HEARTRATE_WRITE, + Scope.HEALTHKIT_HEIGHTWEIGHT_READ, + Scope.HEALTHKIT_HEIGHTWEIGHT_WRITE, + Scope.HEALTHKIT_LOCATION_READ, + Scope.HEALTHKIT_LOCATION_WRITE, + Scope.HEALTHKIT_PULMONARY_READ, + Scope.HEALTHKIT_PULMONARY_WRITE, + Scope.HEALTHKIT_SLEEP_READ, + Scope.HEALTHKIT_SLEEP_WRITE, + Scope.HEALTHKIT_SPEED_READ, + Scope.HEALTHKIT_SPEED_WRITE, + Scope.HEALTHKIT_STEP_READ, + Scope.HEALTHKIT_STEP_WRITE, + Scope.HEALTHKIT_STRENGTH_READ, + Scope.HEALTHKIT_STRENGTH_WRITE, + Scope.HEALTHKIT_BODYFAT_READ, + Scope.HEALTHKIT_BODYFAT_WRITE, + Scope.HEALTHKIT_NUTRITION_READ, + Scope.HEALTHKIT_NUTRITION_WRITE, + Scope.HEALTHKIT_BLOODPRESSURE_READ, + Scope.HEALTHKIT_BLOODPRESSURE_WRITE, + Scope.HEALTHKIT_BODYTEMPERATURE_READ, + Scope.HEALTHKIT_BODYTEMPERATURE_WRITE, + Scope.HEALTHKIT_OXYGENSTATURATION_READ, + Scope.HEALTHKIT_OXYGENSTATURATION_WRITE, + Scope.HEALTHKIT_REPRODUCTIVE_READ, + Scope.HEALTHKIT_REPRODUCTIVE_WRITE, + Scope.HEALTHKIT_ACTIVITY_RECORD_READ, + Scope.HEALTHKIT_ACTIVITY_RECORD_WRITE, + Scope.HEALTHKIT_HEARTRATE_REALTIME, + Scope.HEALTHKIT_STEP_REALTIME, + Scope.HEALTHKIT_HEARTHEALTH_WRITE, + Scope.HEALTHKIT_HEARTHEALTH_READ, + Scope.HEALTHKIT_STRESS_WRITE, + Scope.HEALTHKIT_STRESS_READ, + Scope.HEALTHKIT_OXYGEN_SATURATION_WRITE, + Scope.HEALTHKIT_OXYGEN_SATURATION_READ, + Scope.HEALTHKIT_HISTORYDATA_OPEN_WEEK, + Scope.HEALTHKIT_HISTORYDATA_OPEN_MONTH, + Scope.HEALTHKIT_HISTORYDATA_OPEN_YEAR, ]; + try { - bool? result = await SettingController.getHealthAppAuthorization(); - debugPrint( - 'Granted Scopes for result == is $result}', - ); + await HealthAuth.signIn(scopes); + _dataController = await DataController.init(); + if (_dataController == null) { + return Result.error(false); + } return Result.value(true); + } on PlatformException catch (e) { + debugPrint('Error on Huawei authorization: $e'); + return Result.error(false); } catch (e) { - debugPrint('Error on authorization, Error:${e.toString()}'); + debugPrint('Unexpected Huawei init error: $e'); return Result.error(false); } } @override Future getActivity() async { - DataType dataTypeResult = await SettingController.readDataType( - DataType.DT_CONTINUOUS_STEPS_DELTA.name - ); - - + try { + final ReadReply? data = await readDataType( + DataType.DT_CONTINUOUS_CALORIES_BURNT, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap('activity', data, preferredKeys: const ['calories', 'calories_total']); + } catch (e) { + debugPrint('Error getting activity data: $e'); + mappedData['activity'] = []; + } } @override - Future getBloodOxygen() { - throw UnimplementedError(); + Future getBloodOxygen() async { + try { + final ReadReply? data = await readDataType( + HealthDataTypes.DT_INSTANTANEOUS_SPO2, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap( + 'bloodOxygen', + data, + preferredKeys: const ['saturation', 'saturation_last', 'saturation_avg'], + transform: _normalizeSpo2, + ); + } catch (e) { + debugPrint('Error getting blood oxygen data: $e'); + mappedData['bloodOxygen'] = []; + } + } + @override + Future getBodyTemperature() async { + try { + final ReadReply? data = await readDataType( + HealthDataTypes.DT_INSTANTANEOUS_BODY_TEMPERATURE, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap('bodyTemperature', data, preferredKeys: const ['temperature']); + } catch (e) { + debugPrint('Error getting body temperature data: $e'); + mappedData['bodyTemperature'] = []; + } } @override - Future getBodyTemperature() { + FutureOr getHeartRate() async { + try { + final ReadReply? data = await readDataType( + DataType.DT_INSTANTANEOUS_HEART_RATE, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap('heartRate', data, preferredKeys: const ['bpm']); + } catch (e) { + debugPrint('Error getting heart rate data: $e'); + mappedData['heartRate'] = []; + } + } - throw UnimplementedError(); + @override + FutureOr getSleep() async { + try { + final ReadReply? data = await readDataType( + DataType.DT_CONTINUOUS_SLEEP, + _defaultStartDate, + _defaultEndDate, + ); + addSleepDataToMap(data); + } catch (e) { + debugPrint('Error getting sleep data: $e'); + mappedData['sleep'] = []; + } } @override - FutureOr getHeartRate() { - throw UnimplementedError(); + FutureOr getSteps() async { + try { + final ReadReply? data = await readDataType( + DataType.DT_CONTINUOUS_STEPS_DELTA, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap('steps', data, preferredKeys: const ['steps_delta', 'steps', 'step_rate']); + } catch (e) { + debugPrint('Error getting steps data: $e'); + mappedData['steps'] = []; + } } @override - FutureOr getSleep() { - throw UnimplementedError(); + Future> retrieveData() async { + return Result.value(getMappedData()); } @override - FutureOr getSteps() { - throw UnimplementedError(); + FutureOr getDistance() async { + try { + final ReadReply? data = await readDataType( + DataType.DT_CONTINUOUS_DISTANCE_DELTA, + _defaultStartDate, + _defaultEndDate, + ); + addDataToMap('distance', data, preferredKeys: const ['distance_delta', 'distance']); + } catch (e) { + debugPrint('Error getting distance data: $e'); + mappedData['distance'] = []; + } } + Future readDataType( + DataType dataType, + DateTime startTime, + DateTime endTime, + ) async { + final DataCollector dataCollector = DataCollector( + dataType: dataType, + dataGenerateType: DataGenerateType.DATA_TYPE_RAW, + ); - @override - Future retrieveData() { - throw UnimplementedError(); + final ReadOptions readOptions = ReadOptions( + dataCollectors: [dataCollector], + startTime: startTime, + endTime: endTime, + allowRemoteInquiry: true, + )..groupByTime(1, timeUnit: TimeUnit.HOURS); + + try { + return await _dataController?.read(readOptions); + } on PlatformException catch (e) { + debugPrint('Huawei read error for ${dataType.name}: $e'); + return null; + } } - @override - FutureOr getDistance() { - // TODO: implement getDistance - throw UnimplementedError(); + void addDataToMap( + String key, + ReadReply? data, { + List preferredKeys = const [], + double Function(double value)? transform, + }) { + mappedData[key] = []; + if (data == null) { + return; + } + + if (data.groups.isNotEmpty) { + for (final Group group in data.groups) { + for (final SampleSet sampleSet in group.sampleSets ?? []) { + for (final SamplePoint samplePoint in sampleSet.samplePoints) { + _addNumericSampleToMappedData( + key: key, + samplePoint: samplePoint, + preferredKeys: preferredKeys, + groupStartTime: group.startTime, + transform: transform, + ); + } + } + } + return; + } + + for (final SampleSet sampleSet in data.sampleSets) { + for (final SamplePoint samplePoint in sampleSet.samplePoints) { + _addNumericSampleToMappedData( + key: key, + samplePoint: samplePoint, + preferredKeys: preferredKeys, + transform: transform, + ); + } + } + } + + void addSleepDataToMap(ReadReply? data) { + mappedData['sleep'] = []; + if (data == null) { + return; + } + + void appendSleepPoint(SamplePoint samplePoint, {DateTime? groupStart, DateTime? groupEnd}) { + final DateTime? start = samplePoint.startTime ?? groupStart; + final DateTime? end = samplePoint.endTime ?? groupEnd; + + double? value; + if (start != null && end != null && end.isAfter(start)) { + value = end.difference(start).inMinutes / 60; + } + + value ??= _extractNumericValue( + samplePoint, + const ['sleep_state', 'all_sleep_time', 'deep_sleep_time', 'light_sleep_time'], + ); + + if (value == null) { + return; + } + + final String timestamp = + (start ?? samplePoint.samplingTime ?? DateTime.now()).toIso8601String(); + + mappedData['sleep']?.add( + Vitals( + value: value.toStringAsFixed(2), + timestamp: timestamp, + ), + ); + } + + if (data.groups.isNotEmpty) { + for (final Group group in data.groups) { + for (final SampleSet sampleSet in group.sampleSets ?? []) { + for (final SamplePoint samplePoint in sampleSet.samplePoints) { + appendSleepPoint( + samplePoint, + groupStart: group.startTime, + groupEnd: group.endTime, + ); + } + } + } + return; + } + + for (final SampleSet sampleSet in data.sampleSets) { + for (final SamplePoint samplePoint in sampleSet.samplePoints) { + appendSleepPoint(samplePoint); + } + } + } + + void _addNumericSampleToMappedData({ + required String key, + required SamplePoint samplePoint, + required List preferredKeys, + DateTime? groupStartTime, + double Function(double value)? transform, + }) { + final double? numericValue = _extractNumericValue(samplePoint, preferredKeys); + if (numericValue == null) { + return; + } + + final double transformedValue = transform?.call(numericValue) ?? numericValue; + final String timestamp = + (samplePoint.samplingTime ?? samplePoint.startTime ?? groupStartTime ?? DateTime.now()) + .toIso8601String(); + + mappedData[key]?.add( + Vitals( + value: transformedValue.toStringAsFixed(2), + timestamp: timestamp, + ), + ); + } + + double? _extractNumericValue(SamplePoint samplePoint, List preferredKeys) { + final Map values = { + ...samplePoint.pairs, + ...?samplePoint.fieldValues, + }; + + for (final String key in preferredKeys) { + final dynamic value = values[key]; + if (value is num) { + return value.toDouble(); + } + } + + for (final dynamic value in values.values) { + if (value is num) { + return value.toDouble(); + } + } + + return null; + } + + double _normalizeSpo2(double value) { + if (value <= 1) { + return value * 100; + } + return value; + } + + String getMappedData() { + return jsonEncode({ + 'heartRate': (mappedData['heartRate'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'sleep': (mappedData['sleep'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'steps': (mappedData['steps'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'activity': (mappedData['activity'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'bloodOxygen': + (mappedData['bloodOxygen'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'bodyTemperature': + (mappedData['bodyTemperature'] ?? []).map((Vitals v) => v.toJson()).toList(), + 'distance': (mappedData['distance'] ?? []).map((Vitals v) => v.toJson()).toList(), + }); } +} -} \ No newline at end of file diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index 9658edbe..ea64dfaa 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -57,7 +57,8 @@ class DefaultFirebaseOptions { databaseURL: 'https://api-project-815750722565.firebaseio.com', storageBucket: 'api-project-815750722565.firebasestorage.app', androidClientId: '815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com', - iosBundleId: 'com.cloudsolutions.HMGPatientApp', + // iosBundleId: 'com.cloudsolutions.HMGPatientApp', + iosBundleId: 'com.HMG.HMG-Smartphone', ); } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index ed2074c0..5e527909 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -132,6 +132,7 @@ Future callInitializations() async { } catch (e) { // If it doesn't exist, initialize it. await Firebase.initializeApp( + name: "api-project-815750722565", options: DefaultFirebaseOptions.currentPlatform, ); } diff --git a/lib/presentation/appointments/appointment_details_page.dart b/lib/presentation/appointments/appointment_details_page.dart index 7d1d3f91..874c97c6 100644 --- a/lib/presentation/appointments/appointment_details_page.dart +++ b/lib/presentation/appointments/appointment_details_page.dart @@ -338,6 +338,7 @@ class _AppointmentDetailsPageState extends State { myAppointmentsViewModel.updateListWRTTab(0); await myAppointmentsViewModel.cancelAppointment( patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, + isReschedule: false, onSuccess: (apiResponse) async { LoaderBottomSheet.hideLoader(); myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); diff --git a/lib/presentation/appointments/appointment_payment_page.dart b/lib/presentation/appointments/appointment_payment_page.dart index 5b7e4c80..bef2df93 100644 --- a/lib/presentation/appointments/appointment_payment_page.dart +++ b/lib/presentation/appointments/appointment_payment_page.dart @@ -1283,6 +1283,7 @@ class _AppointmentPaymentPageState extends State { currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED", onFailed: (failureResult) async { log("failureResult: ${failureResult.message.toString()}"); + payfortViewModel.addApplePayPayfortResponse(failureResult.response); LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( context, @@ -1293,10 +1294,94 @@ class _AppointmentPaymentPageState extends State { ); }, onSucceeded: (successResult) async { + payfortViewModel.addApplePayPayfortResponse(successResult); LoaderBottomSheet.hideLoader(); log("successResult: ${successResult.responseMessage.toString()}"); selectedPaymentMethod = successResult.paymentOption ?? "VISA"; checkPaymentStatus(); + + // LoaderBottomSheet.showLoader(loadingText: LocaleKeys.checkingPaymentStatusPleaseWait.tr(context: context)); + // await myAppointmentsViewModel.createAdvancePayment( + // paymentMethodName: selectedPaymentMethod, + // projectID: widget.patientAppointmentHistoryResponseModel.projectID, + // clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, + // appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), + // payedAmount: num.parse(myAppointmentsViewModel.patientAppointmentShareResponseModel!.patientShareWithTax!.toString()), + // paymentReference: successResult.fortId!, + // patientID: appState.getAuthenticatedUser()!.patientId.toString(), + // patientType: appState.getAuthenticatedUser()!.patientType!, + // onSuccess: (value) async { + // print(value); + // await myAppointmentsViewModel.addAdvanceNumberRequest( + // advanceNumber: Utils.isVidaPlusProject(widget.patientAppointmentHistoryResponseModel.projectID) + // ? value.data['OnlineCheckInAppointments'][0]['AdvanceNumber_VP'].toString() + // : value.data['OnlineCheckInAppointments'][0]['AdvanceNumber'].toString(), + // paymentReference: successResult.fortId!, + // appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), + // onSuccess: (value) async { + // if (widget.patientAppointmentHistoryResponseModel.isLiveCareAppointment!) { + // //TODO: Implement LiveCare Check-In API Call + // await myAppointmentsViewModel.insertLiveCareVIDARequest( + // clientRequestID: transID, + // patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel, + // onSuccess: (apiResponse) { + // Future.delayed(Duration(milliseconds: 500), () { + // myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); + // myAppointmentsViewModel.initAppointmentsViewModel(); + // myAppointmentsViewModel.getPatientAppointments(true, false); + // + // getIt.get().setIsWalletAmountToBeLoaded(true); + // getIt.get().initHabibWalletProvider(); + // getIt.get().getPatientBalanceAmount(); + // + // LoaderBottomSheet.hideLoader(); + // Navigator.pushAndRemoveUntil( + // context, + // CustomPageRoute( + // page: LandingNavigation(), + // ), + // (r) => false); + // }); + // }, + // onError: (error) {}); + // } else { + // await myAppointmentsViewModel.generateAppointmentQR( + // clinicID: widget.patientAppointmentHistoryResponseModel.clinicID, + // projectID: widget.patientAppointmentHistoryResponseModel.projectID, + // appointmentNo: widget.patientAppointmentHistoryResponseModel.appointmentNo.toString(), + // isFollowUp: myAppointmentsViewModel.patientAppointmentShareResponseModel!.isFollowup!, + // onSuccess: (apiResponse) { + // Future.delayed(Duration(milliseconds: 500), () { + // myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true); + // myAppointmentsViewModel.initAppointmentsViewModel(); + // myAppointmentsViewModel.getPatientAppointments(true, false); + // + // getIt.get().setIsWalletAmountToBeLoaded(true); + // getIt.get().initHabibWalletProvider(); + // getIt.get().getPatientBalanceAmount(); + // + // LoaderBottomSheet.hideLoader(); + // Navigator.pushAndRemoveUntil( + // context, + // CustomPageRoute( + // page: LandingNavigation(), + // ), + // (r) => false); + // }); + // }); + // } + // }); + // }, + // onError: (err) { + // LoaderBottomSheet.hideLoader(); + // showCommonBottomSheetWithoutHeight( + // context, + // child: Utils.getErrorWidget(loadingText: err.toString()), + // callBackFunc: () {}, + // isFullScreen: false, + // isCloseButtonVisible: true, + // ); + // }); }, // projectId: appo.projectID, // serviceTypeEnum: ServiceTypeEnum.appointmentPayment, diff --git a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart index 9d30f976..b205063c 100644 --- a/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart +++ b/lib/presentation/book_appointment/livecare/immediate_livecare_payment_page.dart @@ -1077,6 +1077,7 @@ class _ImmediateLiveCarePaymentPageState extends State { currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED", onFailed: (failureResult) async { log("failureResult: ${failureResult.message.toString()}"); + payfortViewModel.addApplePayPayfortResponse(failureResult.response); showCommonBottomSheetWithoutHeight( context, child: Utils.getErrorWidget(loadingText: failureResult.message.toString()), @@ -678,6 +678,7 @@ class _WalletPaymentConfirmPageState extends State { }, onSucceeded: (successResult) async { log("successResult: ${successResult.responseMessage.toString()}"); + payfortViewModel.addApplePayPayfortResponse(successResult); selectedPaymentMethod = successResult.paymentOption ?? "VISA"; checkPaymentStatus(); }, @@ -830,28 +831,4 @@ class _WalletPaymentConfirmPageState extends State { "", "3"); } - - Future runSafePayment(Map requestParam, {String sdkToken = ""}) async { - dynamic result; - - try { - // Force a 100ms microtask buffer to isolate the UI rendering channel - await Future.delayed(const Duration(milliseconds: 350)); - - result = await FlutterAmazonpaymentservices.normalPay(requestParam, ApiConsts.payFortEnvironmentType, isShowResponsePage: true); - - print("Payment Success Data: ${result.toString()}"); - } on PlatformException catch (e) { - // If the error is the MethodChannel duplicate reply bug, handle it safely - if (e.message != null && e.message!.contains("Reply already submitted")) { - print("Swallowed native channel race-condition crash safely."); - return; - } - - // Process real payment rejection errors here - print("Actual Payment Failure: ${e.details.toString()}"); - } catch (error) { - print("Generic Error: $error"); - } - } } diff --git a/lib/presentation/home/app_update_page.dart b/lib/presentation/home/app_update_page.dart index 37dab487..e59a7e8a 100644 --- a/lib/presentation/home/app_update_page.dart +++ b/lib/presentation/home/app_update_page.dart @@ -76,14 +76,15 @@ class AppUpdatePage extends StatelessWidget { } if (Platform.isIOS) { Utils.openWebView( - // url: "https://itunes.apple.com/app/id733503978", - url: "https://itunes.apple.com/app/id6758851027", + url: "https://itunes.apple.com/app/id733503978", + // url: "https://itunes.apple.com/app/id6758851027", ); } } Future _handleAndroidAppUpdate() async { - const fallbackUrl = "https://play.google.com/store/apps/details?id=com.cloudsolutions.HMGPatientApp"; + // const fallbackUrl = "https://play.google.com/store/apps/details?id=com.cloudsolutions.HMGPatientApp"; + const fallbackUrl = "https://play.google.com/store/apps/details?id=com.ejada.hmg"; try { final info = await InAppUpdate.checkForUpdate(); print("InAppUpdate.checkForUpdate -> $info"); diff --git a/lib/presentation/medical_file/medical_file_page.dart b/lib/presentation/medical_file/medical_file_page.dart index 629ff15c..add423d8 100644 --- a/lib/presentation/medical_file/medical_file_page.dart +++ b/lib/presentation/medical_file/medical_file_page.dart @@ -280,7 +280,7 @@ class _MedicalFilePageState extends State { AppCustomChipWidget( icon: AppAssets.blood_icon, labelText: appState.getUserBloodGroup.isEmpty ? "N/A" : appState.getUserBloodGroup, - iconColor: AppColors.primaryRedColor, + iconColor: AppColors.primaryRedColorBase, labelPadding: EdgeInsetsDirectional.only(start: -6.w, end: 6.w), padding: EdgeInsets.zero, ), diff --git a/lib/presentation/my_family/widget/family_cards.dart b/lib/presentation/my_family/widget/family_cards.dart index 468dd28f..362aada0 100644 --- a/lib/presentation/my_family/widget/family_cards.dart +++ b/lib/presentation/my_family/widget/family_cards.dart @@ -459,7 +459,7 @@ class _FamilyCardsState extends State { isCircular: true, isFamilyMember: true, // Prevent AppState fallback ), - SizedBox(height: 4.h), + SizedBox(height: 3.h), (profile.patientName ?? "Unknown").toText14(isBold: true, isCenter: true, maxlines: 1), // SizedBox(height: 8.h), // CustomChipWidget( diff --git a/lib/presentation/smartwatches/activity_detail.dart b/lib/presentation/smartwatches/activity_detail.dart index c246d5a0..888533af 100644 --- a/lib/presentation/smartwatches/activity_detail.dart +++ b/lib/presentation/smartwatches/activity_detail.dart @@ -1,5 +1,6 @@ import 'dart:math'; +import 'package:easy_localization/easy_localization.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; @@ -43,7 +44,7 @@ class _ActivityDetailsState extends State { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( - title: "All Health Data".needTranslation, + title: "allHealthData".tr(), child: Column( spacing: 16.h, children: [ @@ -113,8 +114,8 @@ class _ActivityDetailsState extends State { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - widget.sectionName.capitalizeFirstofEach.toText32(isBold: true, color: AppColors.textColor), - "Average".toText12(isBold: true, color: AppColors.greyTextColor) + widget.sectionName.capitalizeFirstofEach.tr().toText32(isBold: true, color: AppColors.textColor), + "average".tr().needTranslation.toText12(isBold: true, color: AppColors.greyTextColor) ], ), Selector>( @@ -242,6 +243,7 @@ class _ActivityDetailsState extends State { builder: (_, data, __) { // if (context.read().selectedData.values.toList().first.isEmpty == true) return SizedBox(); if (context.read().selectedData.values.toList().isEmpty == true) return SizedBox(); + if (context.read().selectedData.values.toList().first.isEmpty == true) return SizedBox(); return CustomBarChart( dataPoints: context.read().selectedData.values.toList().first, diff --git a/lib/presentation/smartwatches/smart_watches_health_data_screen.dart b/lib/presentation/smartwatches/smart_watches_health_data_screen.dart index baa65b49..78e888ad 100644 --- a/lib/presentation/smartwatches/smart_watches_health_data_screen.dart +++ b/lib/presentation/smartwatches/smart_watches_health_data_screen.dart @@ -1,3 +1,4 @@ +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_assets.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; @@ -20,14 +21,14 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( - title: "All Health Data".needTranslation, + title: "allHealthData".tr(context: context), child: Column( spacing: 16.h, children: [ resultItem( leadingIcon: AppAssets.watchActivity, - title: "Activity Calories".needTranslation, - description: "Activity rings give you a quick visual reference of how active you are each day. ".needTranslation, + title: "activityCalories".tr(context: context), + description: "activityCaloriesDescription".tr(context: context), trailingIcon: AppAssets.watchActivityTrailing, result: context.read().sumOfNonEmptyData(context.read().vitals?.activity ?? []), unitsOfMeasure: "Kcal") @@ -36,12 +37,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("activity"); context.read().saveSelectedSection("activity"); context.read().fetchData(); - context.read().navigateToDetails("activity", sectionName: "Activity Calories", uom: "Kcal"); + context.read().navigateToDetails("activity", sectionName: "activityCalories".tr(), uom: "Kcal"); }), resultItem( leadingIcon: AppAssets.watchSteps, - title: "Steps".needTranslation, - description: "Step count is the number of steps you take throughout the day.".needTranslation, + title: "steps".tr(context: context), + description: "stepsDescription".tr(context: context), trailingIcon: AppAssets.watchStepsTrailing, result: context.read().sumOfNonEmptyData(context.read().vitals?.step ?? []), unitsOfMeasure: "Steps") @@ -60,12 +61,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("steps"); context.read().saveSelectedSection("steps"); context.read().fetchData(); - context.read().navigateToDetails("steps", sectionName: "Steps", uom: "Steps"); + context.read().navigateToDetails("steps", sectionName: "steps".tr(), uom: "Steps"); }), resultItem( leadingIcon: AppAssets.watchSteps, - title: "Distance Covered".needTranslation, - description: "Step count is the distance you take throughout the day.".needTranslation, + title: "distanceCovered".tr(context: context), + description: "distanceCoveredDescription".tr(context: context), trailingIcon: AppAssets.watchStepsTrailing, result: context.read().sumOfNonEmptyData(context.read().vitals?.distance ?? []), unitsOfMeasure: "Km") @@ -74,12 +75,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("distance"); context.read().saveSelectedSection("distance"); context.read().fetchData(); - context.read().navigateToDetails("distance", sectionName: "Distance Covered", uom: "km"); + context.read().navigateToDetails("distance", sectionName: "distanceCovered".tr(), uom: "km"); }), resultItem( leadingIcon: AppAssets.watchSleep, - title: "Sleep Score".needTranslation, - description: "This will keep track of how much hours you sleep in a day".needTranslation, + title: "sleepScore".tr(context: context), + description: "sleepScoreDescription".tr(context: context), trailingIcon: AppAssets.watchSleepTrailing, result: DateUtil.millisToHourMin( int.parse(context.read().firstNonEmptyValue(context.read().vitals?.sleep ?? []))) @@ -94,12 +95,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("sleep"); context.read().saveSelectedSection("sleep"); context.read().fetchData(); - context.read().navigateToDetails("sleep", sectionName: "Sleep Score", uom: ""); + context.read().navigateToDetails("sleep", sectionName: "sleepScore".tr(), uom: ""); }), resultItem( leadingIcon: AppAssets.watchWeight, - title: "Blood Oxygen".needTranslation, - description: "This will calculate your Blood Oxygen to keep track and update history".needTranslation, + title: "bloodOxygen".tr(context: context), + description: "bloodOxygenTrackingDescription".tr(context: context), trailingIcon: AppAssets.watchWeightTrailing, result: context.read().firstNonEmptyValue( context.read().vitals?.bodyOxygen ?? [], @@ -110,12 +111,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("bodyOxygen"); context.read().saveSelectedSection("bodyOxygen"); context.read().fetchData(); - context.read().navigateToDetails("bodyOxygen", uom: "%", sectionName: "Blood Oxygen"); + context.read().navigateToDetails("bodyOxygen", uom: "%", sectionName: "bloodOxygen".tr()); }), resultItem( leadingIcon: AppAssets.watchWeight, - title: "Body temperature".needTranslation, - description: "This will calculate your Body temprerature to keep track and update history".needTranslation, + title: "bodyTemperature".tr(context: context), + description: "bodyTemperatureTrackingDescription".tr(context: context), trailingIcon: AppAssets.watchWeightTrailing, result: context.read().firstNonEmptyValue(context.read().vitals?.bodyTemperature ?? []), unitsOfMeasure: "C") @@ -124,7 +125,7 @@ class SmartWatchesHealthDataScreen extends StatelessWidget { context.read().deleteDataIfSectionIsDifferent("bodyTemperature"); context.read().saveSelectedSection("bodyTemperature"); context.read().fetchData(); - context.read().navigateToDetails("bodyTemperature", sectionName: "Body temperature".capitalizeFirstofEach, uom: "C"); + context.read().navigateToDetails("bodyTemperature", sectionName: "bodyTemperature".tr().capitalizeFirstofEach, uom: "C"); }), ], ).paddingSymmetrical(24.w, 24.h), diff --git a/lib/presentation/smartwatches/smartwatch_home_page.dart b/lib/presentation/smartwatches/smartwatch_home_page.dart index 3bd8e9f5..2c3c88ae 100644 --- a/lib/presentation/smartwatches/smartwatch_home_page.dart +++ b/lib/presentation/smartwatches/smartwatch_home_page.dart @@ -25,203 +25,269 @@ class SmartwatchHomePage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.bgScaffoldColor, - body: CollapsingListView( - title: LocaleKeys.smartWatches.tr(), - bottomChild: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.r, + return Consumer(builder: (context, healthProvider, child) { + + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: CollapsingListView( + title: LocaleKeys.smartWatches.tr(), + bottomChild: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + ), + child: CustomButton( + text: LocaleKeys.supportedSmartWatches.tr(context: context), + onPressed: () { + showCommonBottomSheetWithoutHeight( + title: LocaleKeys.supportedSmartWatches.tr(context: context), + context, + child: SupportedWatchesList(), + callBackFunc: () {}, + isFullScreen: false, + isCloseButtonVisible: true, + ); + }, + backgroundColor: AppColors.infoColor.withAlpha(40), + borderColor: AppColors.infoColor.withAlpha(0), + textColor: AppColors.infoColor, + fontSize: 16.f, + isBold: true, + borderRadius: 12.r, + height: 50.h, + icon: AppAssets.ask_doctor_icon, + iconColor: AppColors.infoColor, + iconSize: 18.h, + ).paddingSymmetrical(24.w, 30.h), ), - child: CustomButton( - text: LocaleKeys.supportedSmartWatches.tr(context: context), - onPressed: () { - showCommonBottomSheetWithoutHeight( - title: LocaleKeys.supportedSmartWatches.tr(context: context), - context, - child: SupportedWatchesList(), - callBackFunc: () {}, - isFullScreen: false, - isCloseButtonVisible: true, - ); - }, - backgroundColor: AppColors.infoColor.withAlpha(40), - borderColor: AppColors.infoColor.withAlpha(0), - textColor: AppColors.infoColor, - fontSize: 16.f, - isBold: true, - borderRadius: 12.r, - height: 50.h, - icon: AppAssets.ask_doctor_icon, - iconColor: AppColors.infoColor, - iconSize: 18.h, - ).paddingSymmetrical(24.w, 30.h), - ), - child: SingleChildScrollView( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.h), - child: GridView( - padding: EdgeInsets.zero, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 16.h, - mainAxisSpacing: 16.w, - childAspectRatio: isFoldable ? 1.1 : (isTablet ? 1.3 : 0.7), - ), - children: [ - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.r, - ), - child: Column( - children: [ - Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/apple-watch-5.jpg", width: 136.h, height: 136.h).paddingSymmetrical(24.w, 8.h), - "Apple Watch".needTranslation.toText16(isBold: true), - CustomButton( - text: LocaleKeys.selectSmartWatch.tr(context: context), - onPressed: () { - context - .read() - .setSelectedWatchType(SmartWatchTypes.apple, "assets/images/png/smartwatches/apple-watch-5.jpg"); - getIt.get().pushPage( - page: SmartwatchInstructionsPage( - smartwatchDetails: SmartwatchDetails( - SmartWatchTypes.apple, + child: SingleChildScrollView( + child: Column( + children: [ + Padding( + padding: + EdgeInsets.symmetric(horizontal: 24.w, vertical: 24.h), + child: GridView( + padding: EdgeInsets.zero, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 16.h, + mainAxisSpacing: 16.w, + childAspectRatio: + isFoldable ? 1.1 : (isTablet ? 1.3 : 0.7), + ), + children: [ + Container( + decoration: + RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + ), + child: Column( + children: [ + Utils.buildImgWithAssets( + icon: "assets/images/png/smartwatches/apple-watch-5.jpg", - AppAssets.bluetooth, - LocaleKeys.applehealthapplicationshouldbeinstalledinyourphone.tr(context: context), - LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), - LocaleKeys.applewatchshouldbeconnected.tr(context: context)), - )); - }, - backgroundColor: AppColors.primaryRedColor.withAlpha(40), - borderColor: AppColors.primaryRedColor.withAlpha(0), - textColor: AppColors.primaryRedColor, - fontSize: 14.f, - isBold: true, - borderRadius: 12.r, - height: 40.h, - ).paddingSymmetrical(16.w, 12.h), - ], + width: 136.h, + height: 136.h) + .paddingSymmetrical(24.w, 8.h), + "applewatch" + .tr() + .needTranslation + .toText16(isBold: true), + CustomButton( + text: LocaleKeys.selectSmartWatch + .tr(context: context), + onPressed: () { + context.read().setSelectedWatchType( + SmartWatchTypes.apple, + "assets/images/png/smartwatches/apple-watch-5.jpg"); + getIt.get().pushPage( + page: SmartwatchInstructionsPage( + smartwatchDetails: SmartwatchDetails( + SmartWatchTypes.apple, + "assets/images/png/smartwatches/apple-watch-5.jpg", + AppAssets.bluetooth, + LocaleKeys + .applehealthapplicationshouldbeinstalledinyourphone + .tr(context: context), + LocaleKeys + .unabletodetectapplicationinstalledpleasecomebackonceinstalled + .tr(context: context), + LocaleKeys.applewatchshouldbeconnected + .tr(context: context)), + )); + }, + backgroundColor: + AppColors.primaryRedColor.withAlpha(40), + borderColor: + AppColors.primaryRedColor.withAlpha(0), + textColor: AppColors.primaryRedColor, + fontSize: 14.f, + isBold: true, + borderRadius: 12.r, + height: 40.h, + ).paddingSymmetrical(16.w, 12.h), + ], + ), ), - ), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 24.r), - child: Column( - children: [ - Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", fit: BoxFit.contain, width: 136.w, height: 136.h) - .paddingSymmetrical(24.w, 8.h), - "Samsung Watch".needTranslation.toText16(isBold: true), - CustomButton( - text: LocaleKeys.selectSmartWatch.tr(context: context), - onPressed: () { - context - .read() - .setSelectedWatchType(SmartWatchTypes.samsung, "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg"); - getIt.get().pushPage( - page: SmartwatchInstructionsPage( - smartwatchDetails: SmartwatchDetails( - SmartWatchTypes.samsung, + Container( + decoration: RoundedRectangleBorder() + .toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r), + child: Column( + children: [ + Utils.buildImgWithAssets( + icon: "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", - AppAssets.bluetooth, - LocaleKeys.samsunghealthapplicationshouldbeinstalledinyourphone.tr(context: context), - LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), - LocaleKeys.samsungwatchshouldbeconnected.tr(context: context)), - )); - }, - backgroundColor: AppColors.primaryRedColor.withAlpha(40), - borderColor: AppColors.primaryRedColor.withAlpha(0), - textColor: AppColors.primaryRedColor, - fontSize: 14.f, - isBold: true, - borderRadius: 12.r, - height: 40.h, - ).paddingSymmetrical(16.w, 12.h), - ], + fit: BoxFit.contain, + width: 136.w, + height: 136.h) + .paddingSymmetrical(24.w, 8.h), + "samsungwatch" + .tr() + .needTranslation + .toText16(isBold: true), + CustomButton( + text: LocaleKeys.selectSmartWatch + .tr(context: context), + onPressed: () { + context.read().setSelectedWatchType( + SmartWatchTypes.samsung, + "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg"); + getIt.get().pushPage( + page: SmartwatchInstructionsPage( + smartwatchDetails: SmartwatchDetails( + SmartWatchTypes.samsung, + "assets/images/png/smartwatches/galaxy_watch_8_classic.jpeg", + AppAssets.bluetooth, + LocaleKeys + .samsunghealthapplicationshouldbeinstalledinyourphone + .tr(context: context), + LocaleKeys + .unabletodetectapplicationinstalledpleasecomebackonceinstalled + .tr(context: context), + LocaleKeys + .samsungwatchshouldbeconnected + .tr(context: context)), + )); + }, + backgroundColor: + AppColors.primaryRedColor.withAlpha(40), + borderColor: + AppColors.primaryRedColor.withAlpha(0), + textColor: AppColors.primaryRedColor, + fontSize: 14.f, + isBold: true, + borderRadius: 12.r, + height: 40.h, + ).paddingSymmetrical(16.w, 12.h), + ], + ), ), - ), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.r, + Container( + decoration: + RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + ), + child: Column( + children: [ + Utils.buildImgWithAssets( + icon: + "assets/images/png/smartwatches/Huawei_Watch.png", + width: 136.w, + height: 136.h) + .paddingSymmetrical(24.w, 8.h), + "huaweiwatch" + .tr() + .needTranslation + .toText16(isBold: true), + CustomButton( + text: LocaleKeys.selectSmartWatch + .tr(context: context), + onPressed: () { + // context.read().setSelectedWatchType(SmartWatchTypes.huawei, "assets/images/png/smartwatches/Huawei_Watch.png"); + // getIt.get().pushPage(page: SmartwatchInstructionsPage( + // smartwatchDetails: SmartwatchDetails(SmartWatchTypes.huawei, + // "assets/images/png/smartwatches/Huawei_Watch.png", + // AppAssets.bluetooth, + // LocaleKeys.huaweihealthapplicationshouldbeinstalledinyourphone.tr(context: context), + // LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), + // LocaleKeys.huaweiwatchshouldbeconnected.tr(context: context)), + // )); + showUnavailableDialog(context); + }, + backgroundColor: + AppColors.primaryRedColor.withAlpha(40), + borderColor: + AppColors.primaryRedColor.withAlpha(0), + textColor: AppColors.primaryRedColor, + fontSize: 14.f, + isBold: true, + borderRadius: 12.r, + height: 40.h, + ).paddingSymmetrical(16.w, 12.h), + ], + ), ), - child: Column( - children: [ - Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/Huawei_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h), - "Huawei Watch".needTranslation.toText16(isBold: true), - CustomButton( - text: LocaleKeys.selectSmartWatch.tr(context: context), - onPressed: () { - // context.read().setSelectedWatchType(SmartWatchTypes.huawei, "assets/images/png/smartwatches/Huawei_Watch.png"); - // getIt.get().pushPage(page: SmartwatchInstructionsPage( - // smartwatchDetails: SmartwatchDetails(SmartWatchTypes.huawei, - // "assets/images/png/smartwatches/Huawei_Watch.png", - // AppAssets.bluetooth, - // LocaleKeys.huaweihealthapplicationshouldbeinstalledinyourphone.tr(context: context), - // LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), - // LocaleKeys.huaweiwatchshouldbeconnected.tr(context: context)), - // )); - showUnavailableDialog(context); - }, - backgroundColor: AppColors.primaryRedColor.withAlpha(40), - borderColor: AppColors.primaryRedColor.withAlpha(0), - textColor: AppColors.primaryRedColor, - fontSize: 14.f, - isBold: true, - borderRadius: 12.r, - height: 40.h, - ).paddingSymmetrical(16.w, 12.h), - ], + Container( + decoration: + RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + ), + child: Column( + children: [ + Utils.buildImgWithAssets( + icon: + "assets/images/png/smartwatches/Whoop_Watch.png", + width: 136.w, + height: 136.h) + .paddingSymmetrical(24.w, 8.h), + "whoopwatch" + .tr() + .needTranslation + .toText16(isBold: true), + CustomButton( + text: LocaleKeys.selectSmartWatch + .tr(context: context), + onPressed: () { + showUnavailableDialog(context); + // context.read().setSelectedWatchType(SmartWatchTypes.whoop, "assets/images/png/smartwatches/Whoop_Watch.png"); + // getIt.get().pushPage(page: SmartwatchInstructionsPage( + // smartwatchDetails: SmartwatchDetails(SmartWatchTypes.whoop, + // "assets/images/png/smartwatches/Whoop_Watch.png", + // AppAssets.bluetooth, + // LocaleKeys.whoophealthapplicationshouldbeinstalledinyourphone.tr(context: context), + // LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), + // LocaleKeys.whoopwatchshouldbeconnected.tr(context: context)), + // )); + }, + backgroundColor: + AppColors.primaryRedColor.withAlpha(40), + borderColor: + AppColors.primaryRedColor.withAlpha(0), + textColor: AppColors.primaryRedColor, + fontSize: 14.f, + isBold: true, + borderRadius: 12.r, + height: 40.h, + ).paddingSymmetrical(16.w, 12.h), + ], + ), ), - ), - Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.r, - ), - child: Column( - children: [ - Utils.buildImgWithAssets(icon: "assets/images/png/smartwatches/Whoop_Watch.png", width: 136.w, height: 136.h).paddingSymmetrical(24.w, 8.h), - "Whoop Watch".needTranslation.toText16(isBold: true), - CustomButton( - text: LocaleKeys.selectSmartWatch.tr(context: context), - onPressed: () { - showUnavailableDialog(context); - // context.read().setSelectedWatchType(SmartWatchTypes.whoop, "assets/images/png/smartwatches/Whoop_Watch.png"); - // getIt.get().pushPage(page: SmartwatchInstructionsPage( - // smartwatchDetails: SmartwatchDetails(SmartWatchTypes.whoop, - // "assets/images/png/smartwatches/Whoop_Watch.png", - // AppAssets.bluetooth, - // LocaleKeys.whoophealthapplicationshouldbeinstalledinyourphone.tr(context: context), - // LocaleKeys.unabletodetectapplicationinstalledpleasecomebackonceinstalled.tr(context: context), - // LocaleKeys.whoopwatchshouldbeconnected.tr(context: context)), - // )); - }, - backgroundColor: AppColors.primaryRedColor.withAlpha(40), - borderColor: AppColors.primaryRedColor.withAlpha(0), - textColor: AppColors.primaryRedColor, - fontSize: 14.f, - isBold: true, - borderRadius: 12.r, - height: 40.h, - ).paddingSymmetrical(16.w, 12.h), - ], - ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); + ); + }); } void showUnavailableDialog(BuildContext context) { @@ -229,7 +295,8 @@ class SmartwatchHomePage extends StatelessWidget { title: LocaleKeys.notice.tr(context: context), context, child: Utils.getWarningWidget( - loadingText: LocaleKeys.featureComingSoonDescription.tr(context: context), + loadingText: + LocaleKeys.featureComingSoonDescription.tr(context: context), isShowActionButtons: false, showOkButton: true, onConfirmTap: () async { diff --git a/lib/presentation/smartwatches/smartwatch_instructions_page.dart b/lib/presentation/smartwatches/smartwatch_instructions_page.dart index 7c0d0b97..fcef1d15 100644 --- a/lib/presentation/smartwatches/smartwatch_instructions_page.dart +++ b/lib/presentation/smartwatches/smartwatch_instructions_page.dart @@ -21,65 +21,76 @@ class SmartwatchInstructionsPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: AppColors.bgScaffoldColor, - body: CollapsingListView( - title: "How does it work".needTranslation, - bottomChild: Container( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration( - color: AppColors.whiteColor, - borderRadius: 24.r, - ), - child: CustomButton( - text: LocaleKeys.getStarted.tr(context: context), - onPressed: () { - context.read().initDevice(); - }, - backgroundColor: AppColors.primaryRedColor, - borderColor: AppColors.primaryRedColor, - textColor: AppColors.whiteColor, - fontSize: 16.f, - isBold: true, - borderRadius: 12.r, - height: 50.h, - ).paddingSymmetrical(24.w, 30.h), - ), - child: Column( - mainAxisSize: MainAxisSize.max, - spacing: 18.h, - children: [ - Utils.buildImgWithAssets( - icon: smartwatchDetails.watchIcon, - fit: BoxFit.contain, - height: 280.h, - width: 280.w, + return Consumer(builder: (context, healthProvider, child) { + final errorMessage = healthProvider.error; + if (errorMessage != null && errorMessage.isNotEmpty) { + WidgetsBinding.instance.addPostFrameCallback((_) { + Utils.showToast(errorMessage, longDuration: false); + healthProvider.clearError(); + }); + } + return Scaffold( + backgroundColor: AppColors.bgScaffoldColor, + body: CollapsingListView( + title: "smartwatchHowItWorks".tr(context: context), + bottomChild: Container( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration( + color: AppColors.whiteColor, + borderRadius: 24.r, + ), + child: CustomButton( + text: LocaleKeys.getStarted.tr(context: context), + onPressed: () { + context.read().initDevice(); + }, + backgroundColor: AppColors.primaryRedColor, + borderColor: AppColors.primaryRedColor, + textColor: AppColors.whiteColor, + fontSize: 16.f, + isBold: true, + borderRadius: 12.r, + height: 50.h, + ).paddingSymmetrical(24.w, 30.h), ), - DecoratedBox( - decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), - child: Column( - children: [ - watchContentDetails( - title: smartwatchDetails.detailsTitle, - description: smartwatchDetails.details, - icon: smartwatchDetails.smallIcon, - descriptionTextColor: AppColors.primaryRedColor, - ), - Divider( - color: AppColors.dividerColor, - thickness: 1.h, - ).paddingOnly(top: 16.h, bottom: 16.h), - watchContentDetails( - title: smartwatchDetails.secondTitle, - description: LocaleKeys.updatetheinformation.tr(), - icon: AppAssets.bluetooth, - descriptionTextColor: AppColors.greyTextColor, - ), - ], - ).paddingSymmetrical(16.w, 16.h), - ) - ], - ).paddingSymmetrical(24.w, 16.h), - ), + child: Column( + mainAxisSize: MainAxisSize.max, + spacing: 18.h, + children: [ + Utils.buildImgWithAssets( + icon: smartwatchDetails.watchIcon, + fit: BoxFit.contain, + height: 280.h, + width: 280.w, + ), + DecoratedBox( + decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), + child: Column( + children: [ + watchContentDetails( + title: smartwatchDetails.detailsTitle, + // description: smartwatchDetails.details, + description: "", + icon: smartwatchDetails.smallIcon, + descriptionTextColor: AppColors.primaryRedColor, + ), + Divider( + color: AppColors.dividerColor, + thickness: 1.h, + ).paddingOnly(top: 16.h, bottom: 16.h), + watchContentDetails( + title: smartwatchDetails.secondTitle, + description: LocaleKeys.updatetheinformation.tr(), + icon: AppAssets.bluetooth, + descriptionTextColor: AppColors.greyTextColor, + ), + ], + ).paddingSymmetrical(16.w, 16.h), + ) + ], + ).paddingSymmetrical(24.w, 16.h), + ), + ); + } ); } diff --git a/lib/presentation/todo_section/ancillary_order_payment_page.dart b/lib/presentation/todo_section/ancillary_order_payment_page.dart index 365dff2b..e6665037 100644 --- a/lib/presentation/todo_section/ancillary_order_payment_page.dart +++ b/lib/presentation/todo_section/ancillary_order_payment_page.dart @@ -819,6 +819,7 @@ class _AncillaryOrderPaymentPageState extends State { applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest, currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED", onFailed: (failureResult) async { + payfortViewModel.addApplePayPayfortResponse(failureResult.response); log("failureResult: ${failureResult.message.toString()}"); LoaderBottomSheet.hideLoader(); showCommonBottomSheetWithoutHeight( @@ -830,6 +831,7 @@ class _AncillaryOrderPaymentPageState extends State { ); }, onSucceeded: (successResult) async { + payfortViewModel.addApplePayPayfortResponse(successResult); LoaderBottomSheet.hideLoader(); log("successResult: ${successResult.responseMessage.toString()}"); selectedPaymentMethod = successResult.paymentOption ?? "VISA"; diff --git a/lib/services/localauth_service.dart b/lib/services/localauth_service.dart index 2875a7fe..cdce9005 100644 --- a/lib/services/localauth_service.dart +++ b/lib/services/localauth_service.dart @@ -17,10 +17,12 @@ class LocalAuthService { final isAuthenticated = await localAuth.authenticate( localizedReason: 'Please authenticate to proceed', - options: const AuthenticationOptions( - biometricOnly: true, - stickyAuth: true, - ), + persistAcrossBackgrounding: false, // Replaces stickyAuth + biometricOnly: true, + // options: const AuthenticationOptions( + // biometricOnly: true, + // stickyAuth: true, + // ), ); return isAuthenticated; diff --git a/lib/services/security_service.dart b/lib/services/security_service.dart index b72dffeb..2af9c45a 100644 --- a/lib/services/security_service.dart +++ b/lib/services/security_service.dart @@ -82,7 +82,7 @@ class SecurityServiceImpl implements SecurityService { onObfuscationIssues: () => _handleThreat('Obfuscation Issues', ThreatSeverity.warning), onDebug: () => _handleThreat('Debug Mode', ThreatSeverity.critical), onDeviceBinding: () => _handleThreat('Device Binding', ThreatSeverity.critical), - onDeviceID: () => _handleThreat('Device ID Mismatch', ThreatSeverity.critical), + onDeviceID: () => _handleThreat('Device ID Mismatch', ThreatSeverity.warning), onHooks: () => _handleThreat('Hooks Detected', ThreatSeverity.critical), onPasscode: () => _handleThreat('Passcode Not Set', ThreatSeverity.warning), onPrivilegedAccess: () => _handleThreat('Privileged Access (Root/Jailbreak)', ThreatSeverity.critical), diff --git a/lib/splashPage.dart b/lib/splashPage.dart index 8ebe655e..b1d03c80 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -93,16 +93,12 @@ class _SplashScreenState extends State { if (isAppOpenedFromCall) { navigateToTeleConsult(); } else { - if (Utils.havePrivilege(124)) { - Navigator.of(getIt.get().navigatorKey.currentContext!).pushAndRemoveUntil(CustomPageRoute(page: AppClosedPage()), (r) => false); + if (await Utils.getBoolFromPrefs(CacheConst.firstLaunch)) { + // Navigator.of(context).pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: OnboardingScreen()))); + Navigator.of(getIt.get().navigatorKey.currentContext!).pushReplacement(FadePage(page: OnboardingScreen())); } else { - if (await Utils.getBoolFromPrefs(CacheConst.firstLaunch)) { - // Navigator.of(context).pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: OnboardingScreen()))); - Navigator.of(getIt.get().navigatorKey.currentContext!).pushReplacement(FadePage(page: OnboardingScreen())); - } else { - // Navigator.of(context).pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: LandingNavigation()))); - Navigator.of(getIt.get().navigatorKey.currentContext!).pushReplacement(FadePage(page: LandingNavigation())); - } + // Navigator.of(context).pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: LandingNavigation()))); + Navigator.of(getIt.get().navigatorKey.currentContext!).pushReplacement(FadePage(page: LandingNavigation())); } } } @@ -127,24 +123,24 @@ class _SplashScreenState extends State { // Set initial app context tags try { final appState = getIt.get(); - + // Set device and app metadata Clarity.setCustomTag('app_version', ApiConsts.appVersionID.toString()); Clarity.setCustomTag('device_type', appState.deviceTypeID ?? 'unknown'); Clarity.setCustomTag('platform', Platform.isIOS ? 'ios' : 'android'); - + // Set user context if authenticated if (appState.isAuthenticated) { final user = appState.getAuthenticatedUser(); if (user != null) { // Set user ID for session tracking Clarity.setCustomUserId(user.patientId.toString()); - + // Set custom tags for filtering sessions Clarity.setCustomTag('user_type', user.patientType?.toString() ?? 'unknown'); Clarity.setCustomTag('user_segment', user.outSa == 0 ? 'in_sa' : 'out_sa'); Clarity.setCustomTag('auth_status', 'authenticated'); - + // Optional: Set other non-sensitive user properties if (user.mobileNumber != null) { // Mask phone number for privacy (show only last 4 digits) @@ -155,10 +151,9 @@ class _SplashScreenState extends State { } else { Clarity.setCustomTag('auth_status', 'guest'); } - + // Send initialization event Clarity.sendCustomEvent('app_initialized'); - } catch (e) { debugPrint('Failed to set Clarity user context: $e'); } @@ -171,8 +166,7 @@ class _SplashScreenState extends State { // GetIt.instance().remove(key: CacheConst.isAppOpenedFromCall); Utils.removeFromPrefs(CacheConst.isAppOpenedFromCall); - Navigator.of(GetIt.instance().navigatorKey.currentContext!) - .pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: LandingNavigation()))); + Navigator.of(GetIt.instance().navigatorKey.currentContext!).pushReplacement(FadePage(page: SplashAnimationScreen(routeWidget: LandingNavigation()))); Navigator.pushReplacementNamed( // context, GetIt.instance().navigatorKey.currentContext!, @@ -392,8 +386,6 @@ class _SplashScreenState extends State { Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.whiteColor, - body: Lottie.asset(AppAnimations.loadingAnimation, - repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.fill) - .center); + body: Lottie.asset(AppAnimations.loadingAnimation, repeat: true, reverse: false, frameRate: FrameRate(60), width: 80.h, height: 80.h, fit: BoxFit.fill).center); } } diff --git a/pubspec.lock b/pubspec.lock index d2ea7b16..70ddfc04 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -117,10 +117,10 @@ packages: dependency: transitive description: name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.0" chewie: dependency: transitive description: @@ -1105,6 +1105,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.12.0+301" + huawei_push: + dependency: "direct main" + description: + name: huawei_push + sha256: acc149482c03d0efe3ae50236b1a0aac9c0808cba07ad4eb41f06475b04c06f6 + url: "https://pub.dev" + source: hosted + version: "6.15.0+300" image: dependency: transitive description: @@ -1397,26 +1405,26 @@ packages: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.13.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.0" mime: dependency: transitive description: @@ -2010,10 +2018,10 @@ packages: dependency: transitive description: name: test_api - sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55 url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.7" time: dependency: transitive description: @@ -2295,5 +2303,5 @@ packages: source: hosted version: "1.2.0" sdks: - dart: ">=3.10.0-0 <4.0.0" + dart: ">=3.9.0 <4.0.0" flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index a0b28141..c6bc2c93 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,8 +2,8 @@ name: hmg_patient_app_new description: "New HMG Patient App" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.49+50 -#version: 0.0.17+1 +#version: 4.6.046+1 +version: 4.6.1004+40501004 environment: sdk: ">=3.6.0 <4.0.0" @@ -17,17 +17,17 @@ dependencies: cached_network_image: ^3.4.1 http: ^1.5.0 flutter_svg: ^2.2.0 - shared_preferences: ^2.5.3 - connectivity_plus: ^6.1.5 + shared_preferences: ^2.5.5 + connectivity_plus: ^7.3.1 auto_size_text: ^3.0.0 shimmer: ^3.0.0 sizer: ^3.1.3 easy_localization: ^3.0.8 fluttertoast: ^8.2.12 flutter_rating_bar: ^4.0.1 - firebase_messaging: ^15.2.10 + firebase_messaging: ^16.7.0 # firebase_messaging: any - firebase_core: any + firebase_core: ^4.15.0 # firebase_core: ^3.13.1 permission_handler: ^12.0.1 flutter_local_notifications: ^19.4.1 @@ -45,7 +45,7 @@ dependencies: flutter_ios_voip_kit_karmm: ^0.8.0 image_picker: ^1.2.0 file_picker: 10.3.8 - local_auth: ^2.3.0 + local_auth: ^3.0.2 share_plus: ^11.1.0 device_calendar_plus: path: ./package/device_calendar_plus @@ -63,18 +63,17 @@ dependencies: geolocator: ^14.0.2 dropdown_search: ^6.0.2 google_maps_flutter: ^2.13.1 - # flutter_zoom_videosdk: 2.1.10 - flutter_zoom_videosdk: ^2.5.10 + flutter_zoom_videosdk: 2.1.10 dart_jsonwebtoken: ^3.2.0 dartz: ^0.10.1 equatable: ^2.0.7 google_api_availability: ^5.0.1 - firebase_analytics: ^11.5.1 - firebase_crashlytics: ^4.3.8 - firebase_remote_config: ^5.5.0 + firebase_analytics: ^12.6.0 + firebase_crashlytics: ^5.4.0 + firebase_remote_config: ^6.7.0 jiffy: ^6.4.3 - # hijri_gregorian_calendar: - # path: /Users/aamir/StudioProjects/hijri_gregorian_calendar +# hijri_gregorian_calendar: +# path: /Users/aamir/StudioProjects/hijri_gregorian_calendar sms_otp_auto_verify: ^2.2.0 web: any flutter_staggered_animations: ^1.1.1 @@ -91,7 +90,7 @@ dependencies: path: package/flutter_swiper_view flutter_callkit_incoming: 3.0.0 in_app_update: ^4.2.5 - # device_preview: ^1.3.1 +# device_preview: ^1.3.1 image_picker_android: ^0.8.13+16 image_picker_platform_interface: ^2.10.0 @@ -102,13 +101,16 @@ dependencies: intl: ^0.20.2 flutter_widget_from_html: ^0.17.1 huawei_map: ^6.12.0+301 + huawei_push: ^6.15.0+300 flutter_image_compress: ^2.3.0 scrollable_positioned_list: ^0.3.8 in_app_review: ^2.0.11 flutter_paytabs_bridge: ^2.7.14 - clarity_flutter: 1.9.0 - flutter_amazonpaymentservices: ^0.0.13 + clarity_flutter: ^1.10.0 +# flutter_amazonpaymentservices: ^0.0.13 + flutter_amazonpaymentservices: + path: ./package/flutter_amazonpaymentservices screen_brightness: ^1.0.1 flutter_screenshot_blocker: ^1.0.4 cloudflare_turnstile: ^3.7.2