Merge branch 'master' into national_day_theme

# Conflicts:
#	android/gradle.properties
national_day_theme
FaizHashmi 2 weeks ago
commit afde7bea77

@ -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"}}]}
{
"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"
}
}
]
}

@ -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")

@ -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",

@ -3,7 +3,7 @@
-keep class com.twilio.common.** { *; }
-keepattributes InnerClasses
-keep class com.ejada.** { *; }
#-keep class com.ejada.** { *; }
-keep class org.webrtc.** { *; }
-keep class com.builttoroam.devicecalendar.** { *; }

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.cloudsolutions.HMGPatientApp">
package="com.ejada.hmg">
<!--
io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
@ -133,7 +133,7 @@
android:name=".Application"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher_local"
android:label="Dr. Alhabib Beta"
android:label="Dr. Alhabib"
android:screenOrientation="sensorPortrait"
android:showOnLockScreen="true"
android:usesCleartextTraffic="true"
@ -267,6 +267,9 @@
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyB6TERnxIr0yJ3qG4ULBZbu0sAD4tGqtng" />
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=116912301" />
<!--
Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java

@ -1,5 +1,5 @@
//package com.cloud.diplomaticquarterapp
package com.cloudsolutions.HMGPatientApp
package com.ejada.hmg
import io.flutter.app.FlutterApplication

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp
package com.ejada.hmg
import android.content.Intent
import android.content.pm.PackageManager
@ -7,7 +7,8 @@ import android.util.Log
import android.view.WindowManager
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi
import com.cloudsolutions.HMGPatientApp.watch.samsung_watch.SamsungWatch
import com.ejada.hmg.watch.samsung_watch.SamsungWatch
import com.ejada.hmg.watch.huawei.HuaweiWatch
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
@ -24,6 +25,7 @@ class MainActivity: FlutterFragmentActivity() {
PenguinInPlatformBridge(flutterEngine, this).create()
SamsungWatch(flutterEngine, this)
HuaweiWatch(flutterEngine, this)
}
override fun onRequestPermissionsResult(

@ -1,14 +1,14 @@
package com.cloudsolutions.HMGPatientApp
package com.ejada.hmg
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.cloudsolutions.HMGPatientApp.penguin.PenguinView
import com.ejada.hmg.penguin.PenguinView
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import com.cloudsolutions.HMGPatientApp.PermissionManager.HostNotificationPermissionManager
import com.cloudsolutions.HMGPatientApp.PermissionManager.HostBgLocationManager
import com.cloudsolutions.HMGPatientApp.PermissionManager.HostGpsStateManager
import com.ejada.hmg.PermissionManager.HostNotificationPermissionManager
import com.ejada.hmg.PermissionManager.HostBgLocationManager
import com.ejada.hmg.PermissionManager.HostGpsStateManager
import io.flutter.plugin.common.MethodChannel
class PenguinInPlatformBridge(

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager;
package com.ejada.hmg.PermissionManager;
import android.content.Context;
import android.content.SharedPreferences;

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager;
package com.ejada.hmg.PermissionManager;
import android.Manifest;
import android.app.Activity;

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager;
package com.ejada.hmg.PermissionManager;
import android.Manifest;
import android.app.Activity;

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager;
package com.ejada.hmg.PermissionManager;
import android.app.Activity;
import android.content.pm.PackageManager;

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager
package com.ejada.hmg.PermissionManager
import android.Manifest

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager
package com.ejada.hmg.PermissionManager
import android.app.Activity
import android.content.Context

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.PermissionManager
package com.ejada.hmg.PermissionManager
// PermissionResultReceiver.kt
import android.content.BroadcastReceiver

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.penguin
package com.ejada.hmg.penguin
enum class PenguinMethod {
// initializePenguin("initializePenguin"),

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.penguin
package com.ejada.hmg.penguin
import android.content.Context
import com.google.gson.Gson

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.penguin
package com.ejada.hmg.penguin
import android.app.Activity
import android.content.Context
@ -12,10 +12,10 @@ import android.view.ViewGroup
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.cloudsolutions.HMGPatientApp.PermissionManager.PermissionManager
import com.cloudsolutions.HMGPatientApp.PermissionManager.PermissionResultReceiver
import com.cloudsolutions.HMGPatientApp.MainActivity
import com.cloudsolutions.HMGPatientApp.PermissionManager.PermissionHelper
import com.ejada.hmg.PermissionManager.PermissionManager
import com.ejada.hmg.PermissionManager.PermissionResultReceiver
import com.ejada.hmg.MainActivity
import com.ejada.hmg.PermissionManager.PermissionHelper
import com.peng.pennavmap.PlugAndPlayConfiguration
import com.peng.pennavmap.PlugAndPlaySDK
import com.peng.pennavmap.enums.InitializationErrorType

@ -0,0 +1,87 @@
package com.ejada.hmg.watch.huawei
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.ejada.hmg.watch.samsung_watch.model.Vitals
import com.huawei.hms.adapter.AvailableAdapter
import com.huawei.hms.adapter.internal.AvailableCode
import com.samsung.android.sdk.health.data.HealthDataStore
import com.samsung.android.sdk.health.data.permission.AccessType
import com.samsung.android.sdk.health.data.permission.Permission
import com.samsung.android.sdk.health.data.request.DataType
import com.samsung.android.sdk.health.data.request.DataTypes
import com.samsung.android.sdk.health.data.request.LocalTimeFilter
import com.samsung.android.sdk.health.data.request.LocalTimeGroup
import com.samsung.android.sdk.health.data.request.LocalTimeGroupUnit
import com.samsung.android.sdk.health.data.request.Ordering
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import java.time.LocalDateTime
import java.time.LocalTime
import com.huawei.hms.hihealth.HuaweiHiHealth
import com.ejada.hmg.MainActivity
class HuaweiWatch(
private var flutterEngine: FlutterEngine,
private var mainActivity: MainActivity
) {
private lateinit var channel: MethodChannel
private lateinit var dataStore: HealthDataStore
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private val TAG = "HuaweiWatch"
private lateinit var vitals: MutableMap<String, List<Vitals>>
companion object {
private const val CHANNEL = "huawei_watch"
}
init{
create()
}
@RequiresApi(Build.VERSION_CODES.O)
fun create() {
Log.d(TAG, "create: is called")
// openTok = OpenTok(mainActivity, flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
when (call.method) {
"init" -> {
init(result)
}
else -> {
result.notImplemented()
}
}
}
}
fun init(result: MethodChannel.Result) {
Log.d(TAG, "onMethodCall: init called")
val mSettingController = HuaweiHiHealth.getSettingController(mainActivity);
val availableAdapter = AvailableAdapter(60400312)
val results= availableAdapter.isHuaweiMobileServicesAvailable(mainActivity) // context indicates a context object.
if (results != AvailableCode.SUCCESS) {
availableAdapter.startResolution(mainActivity, object : AvailableAdapter.AvailableCallBack {
override fun onComplete(result: Int) {
Log.d(TAG, "onComplete result: " + result)
}
})
}
result.success("init success")
}
}

@ -1,12 +1,12 @@
package com.cloudsolutions.HMGPatientApp.watch.samsung_watch
package com.ejada.hmg.watch.samsung_watch
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.cloudsolutions.HMGPatientApp.MainActivity
import com.cloudsolutions.HMGPatientApp.watch.samsung_watch.model.Vitals
import com.ejada.hmg.MainActivity
import com.ejada.hmg.watch.samsung_watch.model.Vitals
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import com.samsung.android.sdk.health.data.HealthDataService
@ -75,12 +75,22 @@ class SamsungWatch(
Permission.of(DataTypes.ACTIVITY_SUMMARY, AccessType.READ),
Permission.of(DataTypes.SLEEP, AccessType.READ),
Permission.of(DataTypes.BODY_TEMPERATURE, AccessType.READ),
Permission.of(DataTypes.EXERCISE, AccessType.READ),
// Permission.of(DataTypes.EXERCISE, AccessType.READ),
// Permission.of(DataTypes.SKIN_TEMPERATURE, AccessType.READ),
// Permission.of(DataTypes.NUTRITION, AccessType.READ),
)
scope.launch {
val typesToTest = listOf(
DataTypes.HEART_RATE,
DataTypes.STEPS,
DataTypes.BLOOD_OXYGEN,
DataTypes.ACTIVITY_SUMMARY,
DataTypes.SLEEP,
DataTypes.BODY_TEMPERATURE,
// DataTypes.EXERCISE
)
scope.launch(Dispatchers.IO) {
try {
var granted = dataStore.getGrantedPermissions(permSet)
@ -89,6 +99,17 @@ class SamsungWatch(
return@launch
}
// for (type in typesToTest) {
// try {
// val result = dataStore.requestPermissions(
// setOf(Permission.of(type, AccessType.READ)),
// mainActivity
// )
// Log.d("PermCheck", "OK: $type and the result is $result")
// } catch (e: Exception) {
// Log.e("PermCheck", "FAILED: $type -> ${e.message}")
// }
// }
granted = dataStore.requestPermissions(permSet, mainActivity)
if (granted.containsAll(permSet)) {
@ -111,7 +132,7 @@ class SamsungWatch(
.setOrdering(Ordering.DESC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val heartRateList = dataStore.readData(readRequest).dataList
processHeartVital(heartRateList)
Log.d("TAG"," the data is ${vitals}")
@ -128,7 +149,7 @@ class SamsungWatch(
.setLocalTimeFilter(localTimeFilter)
.setOrdering(Ordering.ASC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val sleepData = dataStore.readData(readRequest).dataList
processSleepVital(sleepData)
print("the data is $vitals")
@ -147,7 +168,7 @@ class SamsungWatch(
.setOrdering(Ordering.ASC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val steps = dataStore.aggregateData(aggregateRequest)
processStepsCount(steps)
print("the data is $vitals")
@ -166,7 +187,7 @@ class SamsungWatch(
.setOrdering(Ordering.DESC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val activityResult = dataStore.aggregateData(readRequest).dataList
processActivity(activityResult)
Log.d("TAG"," the data is ${vitals}")
@ -201,7 +222,7 @@ class SamsungWatch(
.setOrdering(Ordering.DESC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val bloodOxygenList = dataStore.readData(readRequest).dataList
processBloodOxygen(bloodOxygenList)
Log.d("TAG"," the data is ${vitals}")
@ -219,7 +240,7 @@ class SamsungWatch(
.setOrdering(Ordering.DESC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val bodyTemperatureList = dataStore.readData(readRequest).dataList
processBodyTemperature(bodyTemperatureList)
Log.d("TAG"," the data is ${vitals}")
@ -237,7 +258,7 @@ class SamsungWatch(
.setOrdering(Ordering.DESC)
.build()
scope.launch {
scope.launch(Dispatchers.IO) {
val activityResult = dataStore.aggregateData(readRequest).dataList
processDistance(activityResult)
Log.d("TAG"," the data is ${vitals}")

@ -1,4 +1,4 @@
package com.cloudsolutions.HMGPatientApp.watch.samsung_watch.model
package com.ejada.hmg.watch.samsung_watch.model
data class Vitals(
var value : String = "",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.cloudsolutions.HMGPatientApp">
package="com.cloudsolutions.hmg">
<!--
io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.

@ -54,12 +54,24 @@ allprojects {
}
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "21"
// kotlinOptions {
// jvmTarget = "21"
// }
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
}
subprojects {
project.buildscript.repositories {
google()
mavenCentral()
}
project.repositories {
google()
mavenCentral()
}
afterEvaluate {
if (project.hasProperty("android")) {
project.extensions.findByName("android")?.let { androidExt ->
@ -83,8 +95,11 @@ allprojects {
targetCompatibility = JavaVersion.VERSION_21.toString()
}
project.tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = "21"
// kotlinOptions {
// jvmTarget = "21"
// }
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
}
}
}

File diff suppressed because one or more lines are too long

@ -1,8 +1,9 @@
#org.gradle.jvmargs=-xmx4608m
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
@ -12,3 +13,6 @@ android.enableImpeller=false
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

@ -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

@ -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")

@ -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": "عدد الخطوات المتخذة على مدار اليوم",
@ -2054,5 +2067,8 @@
"importantNotice": "تنبيه هام",
"appDecommissionedText": "تم إيقاف هذا الإصدار من تطبيق الحبيب الطبي.\nللاستمرار في الاستفادة من الخدمات الصحية والسجلات الطبية، يرجى تحميل التطبيق الجديد.",
"appDecommissionedSubText": "نعتذر بشدة عن الإزعاج الناتج عن هذا الانتقال.",
"downloadApp": "حمل التطبيق"
"downloadApp": "حمل التطبيق",
"unread": "غير مقروء",
"read": "مقروءة",
"pendingMedicalReportRequest": "لديك بالفعل طلب معلّق للحصول على تقرير طبي خاص بهذا الموعد. يرجى الانتظار حتى اكتمال الطلب قبل تقديم طلب جديد."
}

@ -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",
@ -2044,7 +2057,10 @@
"importantNotice": "Important Notice",
"appDecommissionedText": "This version of our healthcare application has been officially discontinued. To ensure uninterrupted access to your clinical records, we are transitioning all patients back to our main platform.",
"appDecommissionedSubText": "We sincerely apologize for the inconvenience of this transition.",
"downloadApp": "Download App"
"downloadApp": "Download App",
"unread": "Unread",
"read": "Read",
"pendingMedicalReportRequest": "You already have a pending medical report request for this appointment. Please wait for the request to be completed before submitting a new one."
}

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt</string>
<key>ANDROID_CLIENT_ID</key>
<string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string>
<key>API_KEY</key>
@ -11,11 +15,11 @@
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.cloudsolutions.HMGPatientApp</string>
<string>com.HMG.HMG-Smartphone</string>
<key>PROJECT_ID</key>
<string>api-project-815750722565</string>
<key>STORAGE_BUCKET</key>
<string>api-project-815750722565.firebasestorage.app</string>
<string>api-project-815750722565.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
@ -27,7 +31,7 @@
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:815750722565:ios:34ec03c09e02e21f3c186c</string>
<string>1:815750722565:ios:328ec247a81a2ca23c186c</string>
<key>DATABASE_URL</key>
<string>https://api-project-815750722565.firebaseio.com</string>
</dict>

@ -59,7 +59,7 @@ post_install do |installer|
'PERMISSION_NOTIFICATIONS=1',
]
build_configuration.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64 i386'
build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
build_configuration.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
xcconfig_path = build_configuration.base_configuration_reference.real_path
xcconfig = File.read(xcconfig_path)

@ -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 = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
478CFA932E638C8E0064F3D7 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
478CFA952E6E20A60064F3D7 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
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 = "<group>"; };
61243B422EC5FA3700D46FA0 /* PenguinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinModel.swift; sourceTree = "<group>"; };
61243B432EC5FA3700D46FA0 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = "<group>"; };
@ -81,8 +90,10 @@
76B1D24E2F91BF8000DBBD1B /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = "<group>"; };
76B1D24F2F91BF8000DBBD1B /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = "<group>"; };
76B1D2502F91BF8000DBBD1B /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = "<group>"; };
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 = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
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 = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
/* 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 = "<group>";
@ -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 = "<group>";
@ -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;

@ -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
}

@ -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
}

@ -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)

@ -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"}]}
{
"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
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.815750722565-da8p56le8bd6apsbm9eft0jjl1rtpgkt</string>
<key>ANDROID_CLIENT_ID</key>
<string>815750722565-m14h8mkosm7cnq6uh6rhqr54dn02d705.apps.googleusercontent.com</string>
<key>API_KEY</key>
@ -11,11 +15,11 @@
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>com.cloudsolutions.HMGPatientApp</string>
<string>com.HMG.HMG-Smartphone</string>
<key>PROJECT_ID</key>
<string>api-project-815750722565</string>
<key>STORAGE_BUCKET</key>
<string>api-project-815750722565.firebasestorage.app</string>
<string>api-project-815750722565.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
@ -27,7 +31,7 @@
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:815750722565:ios:34ec03c09e02e21f3c186c</string>
<string>1:815750722565:ios:328ec247a81a2ca23c186c</string>
<key>DATABASE_URL</key>
<string>https://api-project-815750722565.firebaseio.com</string>
</dict>

@ -35,6 +35,7 @@
<string>comgooglemaps</string>
<string>baidumap</string>
<string>iosamap</string>
<string>whatsapp</string>
</array>
<key>LSRequiresIPhoneOS</key>
<true/>
@ -86,17 +87,38 @@
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to enable virtual consultation between patient &amp; doctor</string>
<key>NSMotionUsageDescription</key>
<string>This app requires access to motion detection to count your daily steps.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<string>This app requires motion detection access to function properly.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app requires photo library access to upload profile picture and documents.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>NSRemindersUsageDescription</key>
<string>This app requires calendar access to set reminders for Virtual &amp; Normal Appointments.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app requires speech recognition access to access voice command features.</string>
<key>NSUserActivityTypes</key>
<array/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>

@ -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);
}

@ -316,13 +316,20 @@ class ApiConsts {
static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations";
// ************ static values for Api ****************
static final double appVersionID = 22.3;
// static final double appVersionID = 21.9;
static final double appVersionID = 21.5;
// static final double appVersionID = 50.7;
static final int appChannelId = 3;
static final String appIpAddress = "10.20.10.20";
static final String appGeneralId = "Cs2020@2016\$2958";
static final String sessionID = 'TMRhVmkGhOsvamErw';
// Notification Center GUIDs - Configure these values as per your notification center setup
static final String notificationCenterAppGUID = "SzFwWjI0TjhmSjZreDVsNmc3SDRSdWlxUG1h";
static final String notificationServiceGUID_Login = "D8BD5C76-4B50-4122-81D0-C3AA25DB08A2";
static final String notificationServiceGUID_Registration = "690D3595-A1E1-489A-B9AB-6270E83AD6ED";
static final String notificationServiceGUID_FamilyFile = "318285E4-6221-4A66-8FAF-2265D2B4B24C";
}
// PACKAGES and OFFERS

@ -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;

@ -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

@ -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");

@ -75,6 +75,12 @@ class RequestUtils {
}
request.isRegister = false;
}
request.notificationCenterAppGUID = ApiConsts.notificationCenterAppGUID;
request.notificationCenterAppServiceGUID = isForRegister
? ApiConsts.notificationServiceGUID_Registration
: ApiConsts.notificationServiceGUID_Login;
return request;
}
@ -148,6 +154,12 @@ class RequestUtils {
}
request.deviceTypeID = request.searchType;
request.notificationCenterAppGUID = ApiConsts.notificationCenterAppGUID;
request.notificationCenterAppServiceGUID = (registeredData != null && registeredData.isRegister == true)
? ApiConsts.notificationServiceGUID_Registration
: ApiConsts.notificationServiceGUID_Login;
return request;
}
@ -220,6 +232,13 @@ class RequestUtils {
request.familyRegionID = zipCode == CountryEnum.saudiArabia.countryCode ? 1 : 2;
}
request.notificationCenterAppGUID = ApiConsts.notificationCenterAppGUID;
request.notificationCenterAppServiceGUID = isFormFamilyFile
? ApiConsts.notificationServiceGUID_FamilyFile
: isForRegister
? ApiConsts.notificationServiceGUID_Registration
: ApiConsts.notificationServiceGUID_Login;
return request;
}

@ -222,6 +222,8 @@ class AuthenticationRepoImp implements AuthenticationRepo {
if (isRegister) {
newRequest["activationCode"] = activationCode ?? "0000";
newRequest["isSilentLogin"] = activationCode == null;
newRequest.remove("NotificationCenterAppGUID");
newRequest.remove("NotificationCenterAppSeviceGUID");
} else {
newRequest.activationCode = activationCode ?? "0000";
newRequest.isSilentLogin = activationCode == null;

@ -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);
@ -1518,7 +1519,9 @@ class AuthenticationViewModel extends ChangeNotifier {
LoaderBottomSheet.hideLoader();
if (apiResponse.data["MessageStatus"] == 1) {
LoaderBottomSheet.showLoader(loadingText: "Your medical file has been created successfully. \nPlease proceed to login.");
//TODO: Here We Need to Show a Dialog Of Something in the case of Success.
// Reset registration payload and clear healthId so subsequent logins hit the login endpoint
_appState.getUserRegistrationPayload.healthId = null;
_appState.setUserRegistrationPayload = RegistrationDataModelPayload();
await clearDefaultInputValues(); // This will Clear All Default Values Of User.
Future.delayed(Duration(seconds: 1), () {
LoaderBottomSheet.hideLoader();

@ -31,6 +31,8 @@ class SendActivationRequest {
int? familyRegionID;
bool? isPatientExcluded;
String? turnstileToken;
String? notificationCenterAppGUID;
String? notificationCenterAppServiceGUID;
SendActivationRequest(
{this.patientMobileNumber,
@ -64,7 +66,10 @@ class SendActivationRequest {
this.status,
this.familyRegionID,
this.isPatientExcluded,
this.turnstileToken});
this.turnstileToken,
this.notificationCenterAppGUID,
this.notificationCenterAppServiceGUID
});
SendActivationRequest.fromJson(Map<String, dynamic> json) {
patientMobileNumber = json['PatientMobileNumber'];
@ -99,6 +104,8 @@ class SendActivationRequest {
familyRegionID = json['FamilyRegionID'];
isPatientExcluded = json['IsPatientExcluded'];
turnstileToken = json['TurnstileToken'];
notificationCenterAppGUID = json['NotificationCenterAppGUID'];
notificationCenterAppServiceGUID = json['NotificationCenterAppSeviceGUID'];
}
Map<String, dynamic> toJson() {
@ -141,6 +148,8 @@ class SendActivationRequest {
if (turnstileToken != null) {
data['TurnstileToken'] = turnstileToken;
}
data['NotificationCenterAppGUID'] = notificationCenterAppGUID;
data['NotificationCenterAppSeviceGUID'] = notificationCenterAppServiceGUID;
return data;
}
}

@ -37,7 +37,7 @@ abstract class BookAppointmentsRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> getDoctorFreeSlots(int clinicID, int projectID, int doctorId, bool isBookingForLiveCare,
{bool continueDentalPlan = false, Function(dynamic)? onSuccess, Function(String)? onError});
Future<Either<Failure, GenericApiModel<dynamic>>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel});
Future<Either<Failure, GenericApiModel<dynamic>>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false});
Future<Either<Failure, GenericApiModel<dynamic>>> insertSpecificAppointment(
{required int docID,
@ -483,12 +483,12 @@ class BookAppointmentsRepoImp implements BookAppointmentsRepo {
}
@override
Future<Either<Failure, GenericApiModel>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}) async {
Future<Either<Failure, GenericApiModel>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}) async {
Map<String, dynamic> requestBody = {
"AppointmentID": patientAppointmentHistoryResponseModel.appointmentNo,
"ClinicID": patientAppointmentHistoryResponseModel.clinicID,
"ProjectID": patientAppointmentHistoryResponseModel.projectID,
"CancelToReschadual": false,
"CancelToReschadual": isReschedule,
"EndTime": patientAppointmentHistoryResponseModel.endTime,
"StartTime": patientAppointmentHistoryResponseModel.startTime,
"DoctorID": patientAppointmentHistoryResponseModel.doctorID,

@ -948,8 +948,8 @@ class BookAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await bookAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
Future<void> 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());

@ -864,4 +864,17 @@ class MedicalFileViewModel extends ChangeNotifier {
print("❌ Error updating family member profile image in cache: $e");
}
}
bool checkExistingMedicalReportStatus(PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel) {
bool hasExistingRequest = false;
for (var report in patientMedicalReportRequestedList) {
if (report.clinicID == patientAppointmentHistoryResponseModel.clinicID && report.doctorID == patientAppointmentHistoryResponseModel.doctorID) {
hasExistingRequest = true;
break;
}
}
return hasExistingRequest;
}
}

@ -44,7 +44,7 @@ abstract class MyAppointmentsRepo {
Future<Either<Failure, GenericApiModel<dynamic>>> generateAppointmentQR({required int clinicID, required int projectID, required String appointmentNo, required int isFollowUp});
Future<Either<Failure, GenericApiModel<dynamic>>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel});
Future<Either<Failure, GenericApiModel<dynamic>>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false});
Future<Either<Failure, GenericApiModel<dynamic>>> confirmAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel});
@ -341,12 +341,12 @@ class MyAppointmentsRepoImp implements MyAppointmentsRepo {
}
@override
Future<Either<Failure, GenericApiModel>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel}) async {
Future<Either<Failure, GenericApiModel>> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, bool isReschedule = false}) async {
Map<String, dynamic> requestBody = {
"AppointmentID": patientAppointmentHistoryResponseModel.appointmentNo,
"ClinicID": patientAppointmentHistoryResponseModel.clinicID,
"ProjectID": patientAppointmentHistoryResponseModel.projectID,
"CancelToReschadual": false,
"CancelToReschadual": isReschedule,
"EndTime": patientAppointmentHistoryResponseModel.endTime,
"StartTime": patientAppointmentHistoryResponseModel.startTime,
"DoctorID": patientAppointmentHistoryResponseModel.doctorID,

@ -639,8 +639,8 @@ class MyAppointmentsViewModel extends ChangeNotifier {
);
}
Future<void> cancelAppointment({required PatientAppointmentHistoryResponseModel patientAppointmentHistoryResponseModel, Function(dynamic)? onSuccess, Function(String)? onError}) async {
final result = await myAppointmentsRepo.cancelAppointment(patientAppointmentHistoryResponseModel: patientAppointmentHistoryResponseModel);
Future<void> 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),

@ -13,11 +13,16 @@ class NotificationsViewModel extends ChangeNotifier {
ErrorHandlerService errorHandlerService;
List<NotificationResponseModel> notificationsList = [];
List<NotificationResponseModel> readdNotificationsList = [];
List<NotificationResponseModel> unreadNotificationsList = [];
List<NotificationResponseModel> allNotificationsList = [];
int currentPage = 0;
int pagingSize = 50;
int notificationStatusID = 2; // Default to status 2 (e.g., unread)
int selectedNotificationsTabIndex = 0;
NotificationsViewModel({
required this.notificationsRepo,
required this.errorHandlerService,
@ -35,6 +40,18 @@ class NotificationsViewModel extends ChangeNotifier {
notifyListeners();
}
void onNotificationTabChange(int index) {
selectedNotificationsTabIndex = index;
if (index == 0) {
notificationsList = allNotificationsList;
} else if (index == 1) {
notificationsList = unreadNotificationsList;
} else if (index == 2) {
notificationsList = readdNotificationsList;
}
notifyListeners();
}
setNotificationStatusID(int statusID) {
notificationStatusID = statusID;
notificationsList.clear();
@ -49,6 +66,9 @@ class NotificationsViewModel extends ChangeNotifier {
}) async {
isNotificationsLoading = true;
unreadNotificationsCount = 0;
notificationsList.clear();
notifyListeners();
final result = await notificationsRepo.getAllNotifications(
@ -80,17 +100,37 @@ class NotificationsViewModel extends ChangeNotifier {
hasMoreNotifications = false;
}
notificationsList.addAll(newNotifications);
for (var notification in notificationsList) {
if (notification.isRead == false) {
unreadNotificationsCount++;
try {
notificationsList.addAll(newNotifications);
// allNotificationsList.clear();
// readdNotificationsList.clear();
// unreadNotificationsList.clear();
// for (var notification in notificationsList) {
// if (notification.isRead == false) {
// unreadNotificationsCount++;
// unreadNotificationsList.add(notification);
// } else {
// readdNotificationsList.add(notification);
// }
// }
// Filter out the items directly without a loop
unreadNotificationsList = notificationsList.where((n) => n.isRead == false).toList();
readdNotificationsList = notificationsList.where((n) => n.isRead == true).toList();
// Calculate count based on the new list length
unreadNotificationsCount = unreadNotificationsList.length;
currentPage++;
allNotificationsList = notificationsList;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
currentPage++;
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
} catch (ex) {
print(ex.toString());
}
}
},

@ -68,6 +68,11 @@ class OccasionConfigModel {
enabled: (json['enabled'] as bool?) ?? false,
startDate: _parseDate(json['start_date']),
endDate: _parseDate(json['end_date']),
// enabled: true,
// startDate: _parseDate("2026-09-30T00:00:00Z"),
// endDate: _parseDate("2026-10-07T00:00:00Z"),
primaryColorHex: json['primary_color'] as String?,
backgroundOpacityImage: json['background_opacity_image'] as String?,
backgroundImageOpacity: (json['background_image_opacity'] as num?)?.toDouble() ?? 1.0,

@ -578,4 +578,27 @@ class PayfortViewModel extends ChangeNotifier {
);
}
Future<void> 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);
}
}

@ -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<NavigationService>().pushPage(page: SmartWatchesHealthDataScreen());
}
@ -286,4 +294,9 @@ class HealthProvider with ChangeNotifier {
}
return formattedString;
}
void clearError(){
error = null;
notifyListeners();
}
}

@ -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,

@ -0,0 +1 @@
class IllegalWatchTypeException implements Exception {}

@ -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();
}
}
}

@ -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<Result<bool>> initDevice() async{
try{
await _channel.invokeMethod('init');
}catch(e){
DataController? _dataController;
final Map<String, List<Vitals>> mappedData = <String, List<Vitals>>{};
DateTime get _defaultEndDate => DateTime.now();
DateTime get _defaultStartDate => _defaultEndDate.subtract(const Duration(days: 365));
@override
Future<Result<bool>> 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<Scope> 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<Scope> scopes = <Scope>[
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<void> 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 <String>['calories', 'calories_total']);
} catch (e) {
debugPrint('Error getting activity data: $e');
mappedData['activity'] = <Vitals>[];
}
}
@override
Future getBloodOxygen() {
throw UnimplementedError();
Future<void> getBloodOxygen() async {
try {
final ReadReply? data = await readDataType(
HealthDataTypes.DT_INSTANTANEOUS_SPO2,
_defaultStartDate,
_defaultEndDate,
);
addDataToMap(
'bloodOxygen',
data,
preferredKeys: const <String>['saturation', 'saturation_last', 'saturation_avg'],
transform: _normalizeSpo2,
);
} catch (e) {
debugPrint('Error getting blood oxygen data: $e');
mappedData['bloodOxygen'] = <Vitals>[];
}
}
@override
Future<void> getBodyTemperature() async {
try {
final ReadReply? data = await readDataType(
HealthDataTypes.DT_INSTANTANEOUS_BODY_TEMPERATURE,
_defaultStartDate,
_defaultEndDate,
);
addDataToMap('bodyTemperature', data, preferredKeys: const <String>['temperature']);
} catch (e) {
debugPrint('Error getting body temperature data: $e');
mappedData['bodyTemperature'] = <Vitals>[];
}
}
@override
Future getBodyTemperature() {
FutureOr<void> getHeartRate() async {
try {
final ReadReply? data = await readDataType(
DataType.DT_INSTANTANEOUS_HEART_RATE,
_defaultStartDate,
_defaultEndDate,
);
addDataToMap('heartRate', data, preferredKeys: const <String>['bpm']);
} catch (e) {
debugPrint('Error getting heart rate data: $e');
mappedData['heartRate'] = <Vitals>[];
}
}
throw UnimplementedError();
@override
FutureOr<void> 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'] = <Vitals>[];
}
}
@override
FutureOr<void> getHeartRate() {
throw UnimplementedError();
FutureOr<void> getSteps() async {
try {
final ReadReply? data = await readDataType(
DataType.DT_CONTINUOUS_STEPS_DELTA,
_defaultStartDate,
_defaultEndDate,
);
addDataToMap('steps', data, preferredKeys: const <String>['steps_delta', 'steps', 'step_rate']);
} catch (e) {
debugPrint('Error getting steps data: $e');
mappedData['steps'] = <Vitals>[];
}
}
@override
FutureOr<void> getSleep() {
throw UnimplementedError();
Future<Result<String>> retrieveData() async {
return Result.value(getMappedData());
}
@override
FutureOr<void> getSteps() {
throw UnimplementedError();
FutureOr<void> getDistance() async {
try {
final ReadReply? data = await readDataType(
DataType.DT_CONTINUOUS_DISTANCE_DELTA,
_defaultStartDate,
_defaultEndDate,
);
addDataToMap('distance', data, preferredKeys: const <String>['distance_delta', 'distance']);
} catch (e) {
debugPrint('Error getting distance data: $e');
mappedData['distance'] = <Vitals>[];
}
}
Future<ReadReply?> 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>[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<void> getDistance() {
// TODO: implement getDistance
throw UnimplementedError();
void addDataToMap(
String key,
ReadReply? data, {
List<String> preferredKeys = const <String>[],
double Function(double value)? transform,
}) {
mappedData[key] = <Vitals>[];
if (data == null) {
return;
}
if (data.groups.isNotEmpty) {
for (final Group group in data.groups) {
for (final SampleSet sampleSet in group.sampleSets ?? <SampleSet>[]) {
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'] = <Vitals>[];
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 <String>['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 ?? <SampleSet>[]) {
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<String> 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<String> preferredKeys) {
final Map<String, dynamic> values = <String, dynamic>{
...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(<String, dynamic>{
'heartRate': (mappedData['heartRate'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'sleep': (mappedData['sleep'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'steps': (mappedData['steps'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'activity': (mappedData['activity'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'bloodOxygen':
(mappedData['bloodOxygen'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'bodyTemperature':
(mappedData['bodyTemperature'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
'distance': (mappedData['distance'] ?? <Vitals>[]).map((Vitals v) => v.toJson()).toList(),
});
}
}
}

@ -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',
);
}

@ -2036,5 +2036,8 @@ abstract class LocaleKeys {
static const appDecommissionedText = 'appDecommissionedText';
static const appDecommissionedSubText = 'appDecommissionedSubText';
static const downloadApp = 'downloadApp';
static const unread = 'unread';
static const read = 'read';
static const pendingMedicalReportRequest = 'pendingMedicalReportRequest';
}

@ -132,6 +132,7 @@ Future<void> callInitializations() async {
} catch (e) {
// If it doesn't exist, initialize it.
await Firebase.initializeApp(
name: "api-project-815750722565",
options: DefaultFirebaseOptions.currentPlatform,
);
}

@ -338,6 +338,7 @@ class _AppointmentDetailsPageState extends State<AppointmentDetailsPage> {
myAppointmentsViewModel.updateListWRTTab(0);
await myAppointmentsViewModel.cancelAppointment(
patientAppointmentHistoryResponseModel: widget.patientAppointmentHistoryResponseModel,
isReschedule: false,
onSuccess: (apiResponse) async {
LoaderBottomSheet.hideLoader();
myAppointmentsViewModel.setIsAppointmentDataToBeLoaded(true);

@ -748,7 +748,8 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
// (myAppointmentsVM.patientAppointmentShareResponseModel!.isCash ?? true)
(true)
? Container(
height: 50.h,
decoration: ShapeDecoration(
@ -1282,6 +1283,7 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
payfortViewModel.addApplePayPayfortResponse(failureResult.response);
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
@ -1292,10 +1294,94 @@ class _AppointmentPaymentPageState extends State<AppointmentPaymentPage> {
);
},
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<HabibWalletViewModel>().setIsWalletAmountToBeLoaded(true);
// getIt.get<HabibWalletViewModel>().initHabibWalletProvider();
// getIt.get<HabibWalletViewModel>().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<HabibWalletViewModel>().setIsWalletAmountToBeLoaded(true);
// getIt.get<HabibWalletViewModel>().initHabibWalletProvider();
// getIt.get<HabibWalletViewModel>().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,

@ -448,7 +448,17 @@ class _AppointmentCardState extends State<AppointmentCard> {
if (widget.isForFeedback) {
widget.contactUsViewModel!.setPatientFeedbackSelectedAppointment(widget.patientAppointmentHistoryResponseModel);
} else {
widget.medicalFileViewModel!.setSelectedMedicalReportAppointment(widget.patientAppointmentHistoryResponseModel);
if(!widget.medicalFileViewModel!.checkExistingMedicalReportStatus(widget.patientAppointmentHistoryResponseModel)) {
widget.medicalFileViewModel!.setSelectedMedicalReportAppointment(widget.patientAppointmentHistoryResponseModel);
} else {
showCommonBottomSheetWithoutHeight(
context,
child: Utils.getErrorWidget(loadingText: LocaleKeys.pendingMedicalReportRequest.tr(context: context)),
callBackFunc: () {},
isFullScreen: false,
isCloseButtonVisible: true,
);
}
}
Navigator.pop(context, false);
} else {

@ -759,8 +759,8 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
.onPress(() async {
// payfortVM.setIsApplePayConfigurationLoading(true);
if (Utils.havePrivilege(103)) {
// startApplePay();
myFatoorahViewModel.executeApplePayPayment();
startApplePay();
// myFatoorahViewModel.executeApplePayPayment();
} else {
openPaymentURL("ApplePay");
}
@ -1077,6 +1077,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
log("failureResult: ${failureResult.message.toString()}");
payfortViewModel.addApplePayPayfortResponse(failureResult.response);
LoaderBottomSheet.hideLoader();
showCommonBottomSheetWithoutHeight(
context,
@ -1087,6 +1088,7 @@ class _ImmediateLiveCarePaymentPageState extends State<ImmediateLiveCarePaymentP
);
},
onSucceeded: (successResult) async {
payfortViewModel.addApplePayPayfortResponse(successResult);
LoaderBottomSheet.hideLoader();
log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";

@ -904,6 +904,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
applePayShaRequestPhrase: payfortViewModel.payfortProjectDetailsRespModel!.shaRequest,
currency: appState.getAuthenticatedUser()!.outSa! == 0 ? "SAR" : "AED",
onFailed: (failureResult) async {
payfortViewModel.addApplePayPayfortResponse(failureResult.response);
log("failureResult: ${failureResult.message.toString()}");
Navigator.of(context).pop();
showCommonBottomSheetWithoutHeight(
@ -915,6 +916,7 @@ class _WaitingAppointmentPaymentPageState extends State<WaitingAppointmentPaymen
);
},
onSucceeded: (successResult) async {
payfortViewModel.addApplePayPayfortResponse(successResult);
log("successResult: ${successResult.responseMessage.toString()}");
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus();

@ -7,7 +7,6 @@ import 'package:clarity_flutter/clarity_flutter.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_amazonpaymentservices/flutter_amazonpaymentservices.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/app_state.dart';
@ -668,6 +667,7 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
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<WalletPaymentConfirmPage> {
},
onSucceeded: (successResult) async {
log("successResult: ${successResult.responseMessage.toString()}");
payfortViewModel.addApplePayPayfortResponse(successResult);
selectedPaymentMethod = successResult.paymentOption ?? "VISA";
checkPaymentStatus();
},
@ -830,28 +831,4 @@ class _WalletPaymentConfirmPageState extends State<WalletPaymentConfirmPage> {
"",
"3");
}
Future<void> runSafePayment(Map<String, dynamic> 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");
}
}
}

@ -72,7 +72,7 @@ class _ServicesPageState extends State<ServicesPage> {
LocaleKeys.emergencyServices.tr(),
"",
AppAssets.emergency_services_icon,
bgColor: AppColors.primaryRedColor,
bgColor: AppColors.primaryRedColorBase,
true,
route: null, onTap: () async {
// if (getIt.get<AppState>().isAuthenticated) {

@ -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<void> _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");

@ -437,6 +437,7 @@ class _LandingPageState extends State<LandingPage> {
: SizedBox.shrink(),
]).onPress(() async {
if (appState.isAuthenticated) {
notificationsViewModel.onNotificationTabChange(0);
notificationsViewModel.setNotificationStatusID(2);
notificationsViewModel.getAllNotifications();
Navigator.of(context).push(

@ -280,7 +280,7 @@ class _MedicalFilePageState extends State<MedicalFilePage> {
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,
),

@ -84,15 +84,15 @@ class MedicalReportCard extends StatelessWidget {
),
);
},
backgroundColor: AppColors.lightRedButtonColor,
borderColor: AppColors.lightRedButtonColor,
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
textColor: AppColors.primaryRedColor,
iconColor: AppColors.primaryRedColor,
fontSize: 14.f,
// fontWeight: FontWeight.w600,
isBold: true,
borderRadius: 12.r,
height: 40.h,
iconSize: 18.f,
).toShimmer2(isShow: isLoading),
],
),

@ -122,7 +122,7 @@ class PatientSickLeaveCard extends StatelessWidget {
});
},
backgroundColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.secondaryLightRedColor,
borderColor: AppColors.transparent,
textColor: AppColors.primaryRedColor,
fontSize: 14.f,
isBold: true,

@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
@ -26,8 +27,9 @@ class MedicalReportRequestPage extends StatelessWidget {
isClose: true,
child: Column(
children: [
ListView.separated(
padding: EdgeInsets.only(top: 24.h),
medicalFileViewModel.patientMedicalReportAppointmentHistoryList.isNotEmpty
? ListView.separated(
padding: EdgeInsets.only(top: 24.h),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: medicalFileViewModel.patientMedicalReportAppointmentHistoryList.length,
@ -57,7 +59,8 @@ class MedicalReportRequestPage extends StatelessWidget {
);
},
separatorBuilder: (BuildContext cxt, int index) => SizedBox(height: 16.h),
),
)
: Utils.getNoDataWidget(context),
SizedBox(height: 24.h),
],
),

@ -50,42 +50,7 @@ class _MedicalReportsPageState extends State<MedicalReportsPage> {
child: Consumer<MedicalFileViewModel>(builder: (context, medicalFileVM, child) {
return Column(
children: [
SizedBox(height: 16.h),
// Status filter tabs
// Row(
// children: [
// CustomButton(
// text: LocaleKeys.byClinic.tr(context: context),
// onPressed: () {
// medicalFileVM.setIsMedicalReportsSortByClinic(true);
// },
// backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.bgRedLightColor : AppColors.whiteColor,
// borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
// textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.primaryRedColor : AppColors.blackColor,
// fontSize: 12,
// isBold: true,
// borderRadius: 10,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// SizedBox(width: 8.h),
// CustomButton(
// text: LocaleKeys.byHospital.tr(context: context),
// onPressed: () {
// medicalFileVM.setIsMedicalReportsSortByClinic(false);
// },
// backgroundColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.whiteColor : AppColors.bgRedLightColor,
// borderColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.textColor.withValues(alpha: 0.2) : AppColors.primaryRedColor,
// textColor: medicalFileVM.isMedicalReportsSortByClinic ? AppColors.blackColor : AppColors.primaryRedColor,
// fontSize: 12,
// isBold: true,
// borderRadius: 10,
// padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
// height: 40.h,
// ),
// ],
// ).paddingSymmetrical(24.h, 0.h),
SizedBox(height: 8.h),
SizedBox(height: 24.h),
Row(
children: [
CustomButton(
@ -404,6 +369,7 @@ class _MedicalReportsPageState extends State<MedicalReportsPage> {
showCommonBottomSheetWithoutHeight(context,
child: Utils.getSuccessWidget(loadingText: LocaleKeys.yourMedicalReportRequestSubmittedSuccessfully.tr(context: context)),
callBackFunc: () async{
medicalFileViewModel.setIsMedicalReportsDataNeedsReloading(true);
medicalFileViewModel.setIsPatientMedicalReportsLoading(true);
medicalFileViewModel.onMedicalReportTabChange(0);
medicalFileViewModel.getPatientMedicalReportList();

@ -459,7 +459,7 @@ class _FamilyCardsState extends State<FamilyCards> {
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(
@ -475,7 +475,7 @@ class _FamilyCardsState extends State<FamilyCards> {
? Wrap(direction: Axis.horizontal, spacing: 4.h, runSpacing: 4.h, children: [
AppCustomChipWidget(
icon: AppAssets.file_icon,
richText: "${LocaleKeys.fileno.tr(context: context)}: ${profile.responseId}".toText10(isBold: true),
richText: "${profile.responseId}".toText10(isBold: true),
labelPadding: EdgeInsetsDirectional.only(start: -4.w, end: 6.w),
),
AppCustomChipWidget(
@ -489,7 +489,7 @@ class _FamilyCardsState extends State<FamilyCards> {
: SizedBox(
height: 4.h,
),
Spacer(),
SizedBox(height: 8.h),
widget.isForWalletRecharge
? CustomButton(
height: 40.h,

@ -17,6 +17,7 @@ import 'package:hmg_patient_app_new/presentation/lab/lab_result_item_view.dart';
import 'package:hmg_patient_app_new/presentation/notifications/notification_details_page.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import 'dart:ui' as ui;
@ -51,6 +52,54 @@ class _NotificationsListPageState extends State<NotificationsListPage> {
child: Consumer<NotificationsViewModel>(builder: (context, notificationsVM, child) {
return Column(
children: [
Row(
children: [
CustomButton(
text: LocaleKeys.all.tr(context: context),
onPressed: () {
notificationsVM.onNotificationTabChange(0);
},
backgroundColor: notificationsVM.selectedNotificationsTabIndex == 0 ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: notificationsVM.selectedNotificationsTabIndex == 0 ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: notificationsVM.selectedNotificationsTabIndex == 0 ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12,
isBold: true,
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
SizedBox(width: 8.h),
CustomButton(
text: LocaleKeys.unread.tr(context: context),
onPressed: () {
notificationsVM.onNotificationTabChange(1);
},
backgroundColor: notificationsVM.selectedNotificationsTabIndex == 1 ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: notificationsVM.selectedNotificationsTabIndex == 1 ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: notificationsVM.selectedNotificationsTabIndex == 1 ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12,
isBold: true,
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
SizedBox(width: 8.h),
CustomButton(
text: LocaleKeys.read.tr(context: context),
onPressed: () {
notificationsVM.onNotificationTabChange(2);
},
backgroundColor: notificationsVM.selectedNotificationsTabIndex == 2 ? AppColors.bgRedLightColor : AppColors.whiteColor,
borderColor: notificationsVM.selectedNotificationsTabIndex == 2 ? AppColors.primaryRedColor : AppColors.textColor.withValues(alpha: 0.2),
textColor: notificationsVM.selectedNotificationsTabIndex == 2 ? AppColors.primaryRedColor : AppColors.blackColor,
fontSize: 12,
isBold: true,
borderRadius: 10,
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
height: 40.h,
),
],
).paddingSymmetrical(24.h, 0.h),
Container(
margin: EdgeInsets.symmetric(vertical: 24.h),
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(

@ -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<ActivityDetails> {
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<ActivityDetails> {
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<HealthProvider, Tuple2<double?, String?>>(
@ -242,6 +243,7 @@ class _ActivityDetailsState extends State<ActivityDetails> {
builder: (_, data, __) {
// if (context.read<HealthProvider>().selectedData.values.toList().first.isEmpty == true) return SizedBox();
if (context.read<HealthProvider>().selectedData.values.toList().isEmpty == true) return SizedBox();
if (context.read<HealthProvider>().selectedData.values.toList().first.isEmpty == true) return SizedBox();
return CustomBarChart(
dataPoints: context.read<HealthProvider>().selectedData.values.toList().first,

@ -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<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.activity ?? []),
unitsOfMeasure: "Kcal")
@ -36,12 +37,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("activity");
context.read<HealthProvider>().saveSelectedSection("activity");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("activity", sectionName: "Activity Calories", uom: "Kcal");
context.read<HealthProvider>().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<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.step ?? []),
unitsOfMeasure: "Steps")
@ -60,12 +61,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("steps");
context.read<HealthProvider>().saveSelectedSection("steps");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("steps", sectionName: "Steps", uom: "Steps");
context.read<HealthProvider>().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<HealthProvider>().sumOfNonEmptyData(context.read<HealthProvider>().vitals?.distance ?? []),
unitsOfMeasure: "Km")
@ -74,12 +75,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("distance");
context.read<HealthProvider>().saveSelectedSection("distance");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("distance", sectionName: "Distance Covered", uom: "km");
context.read<HealthProvider>().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<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.sleep ?? [])))
@ -94,12 +95,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("sleep");
context.read<HealthProvider>().saveSelectedSection("sleep");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("sleep", sectionName: "Sleep Score", uom: "");
context.read<HealthProvider>().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<HealthProvider>().firstNonEmptyValue(
context.read<HealthProvider>().vitals?.bodyOxygen ?? [],
@ -110,12 +111,12 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyOxygen");
context.read<HealthProvider>().saveSelectedSection("bodyOxygen");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyOxygen", uom: "%", sectionName: "Blood Oxygen");
context.read<HealthProvider>().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<HealthProvider>().firstNonEmptyValue(context.read<HealthProvider>().vitals?.bodyTemperature ?? []),
unitsOfMeasure: "C")
@ -124,7 +125,7 @@ class SmartWatchesHealthDataScreen extends StatelessWidget {
context.read<HealthProvider>().deleteDataIfSectionIsDifferent("bodyTemperature");
context.read<HealthProvider>().saveSelectedSection("bodyTemperature");
context.read<HealthProvider>().fetchData();
context.read<HealthProvider>().navigateToDetails("bodyTemperature", sectionName: "Body temperature".capitalizeFirstofEach, uom: "C");
context.read<HealthProvider>().navigateToDetails("bodyTemperature", sectionName: "bodyTemperature".tr().capitalizeFirstofEach, uom: "C");
}),
],
).paddingSymmetrical(24.w, 24.h),

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save