Compare commits

...

10 Commits

@ -99,8 +99,6 @@ android {
debug {
debuggable true
signingConfig signingConfigs.debug
minifyEnabled false
shrinkResources false
// ndk {
// abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
// }
@ -137,9 +135,6 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
flutter {
@ -189,10 +184,6 @@ dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'androidx.test.ext:junit:1.1.5'
implementation 'com.android.volley:volley:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.8.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.8.5'
implementation 'androidx.activity:activity:1.9.3'
def room_version = "2.4.0-alpha04"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
@ -226,6 +217,4 @@ dependencies {
// implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.22'
implementation 'com.whatsapp.otp:whatsapp-otp-android-sdk:0.1.0'
implementation 'com.whatsapp.otp:whatsapp-otp-android-sdk:0.1.0'
}

@ -1,51 +1,30 @@
<?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.ejada.hmg">
<!--
io.flutter.app.FlutterApplication is an android.app.Application that
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here.
-->
<uses-permission
android:name="android.permission.ACTIVITY_RECOGNITION"
tools:node="remove" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"
tools:node="remove" /> <!-- <uses-permission android:name="android.permission.BLUETOOTH" tools:node="remove"/> -->
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" tools:node="remove"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
<!-- <uses-permission android:name="android.permission.BLUETOOTH" tools:node="remove"/>-->
<!-- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" tools:node="remove"/>-->
<!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" tools:node="remove"/>-->
<!-- <uses-permission android:name="android.permission.BLUETOOTH_SCAN" tools:node="remove"/>-->
<uses-permission
android:name="android.permission.BROADCAST_STICKY"
tools:node="remove" />
<uses-permission
android:name="com.google.android.gms.permission.AD_ID"
tools:node="remove" /> <!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> -->
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE"
tools:node="remove" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"
tools:node="remove" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"
tools:node="remove" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"
tools:node="remove" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"
tools:node="remove" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"
tools:node="remove" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" tools:node="remove"/>
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" tools:node="remove"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" tools:node="remove"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission
android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
tools:node="remove" /> <!-- <uses-permission android:name="android.permission.INTERNET" /> -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" />
<!-- <uses-permission android:name="android.permission.INTERNET" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -55,14 +34,8 @@
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />
<uses-feature
android:name="android.hardware.sensor.stepcounter"
android:required="false"
tools:node="replace" />
<uses-feature
android:name="android.hardware.sensor.stepdetector"
android:required="false"
tools:node="replace" />
<uses-feature android:name="android.hardware.sensor.stepcounter" android:required="false" tools:node="replace"/>
<uses-feature android:name="android.hardware.sensor.stepdetector" android:required="false" tools:node="replace"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.INTERNET" />
@ -71,12 +44,8 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@ -84,135 +53,102 @@
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-feature android:name="android.hardware.location.network" android:required="false" />
<uses-feature android:name="android.hardware.location.gps" android:required="false" />
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>
<!-- <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />-->
<uses-feature
android:name="android.hardware.location.network"
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA" /> <!-- <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" /> -->
<!-- Wifi Permissions-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>-->
<!-- Detect Reboot Permission -->
<!-- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>-->
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
<package android:name="com.whatsapp"/>
<package android:name="com.whatsapp.w4b"/>
</queries>
<application
android:name=".Application"
android:allowBackup="false"
android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher_local"
android:label="Dr. Alhabib"
android:screenOrientation="sensorPortrait"
android:showOnLockScreen="true"
android:usesCleartextTraffic="true"
tools:replace="android:extractNativeLibs,android:label">
<activity
android:name=".WhatsAppCodeActivity"
android:exported="true"
android:enabled="true"
android:launchMode="standard"
>
<intent-filter>
<action android:name="com.whatsapp.otp.OTP_RETRIEVED" />
</intent-filter>
</activity>
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
android:showOnLockScreen="true"
android:screenOrientation="sensorPortrait"
android:allowBackup="false"
android:extractNativeLibs="true"
tools:replace="android:extractNativeLibs,android:label"
android:label="Dr. Alhabib">
<meta-data android:name="push_kit_auto_init_enabled" android:value="true" />
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:enabled="true"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:showOnLockScreen="true"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize"
tools:node="merge">
<!--
Specifies an Android theme to apply to this Activity as soon as
android:exported="true"
android:enabled="true"
tools:node="merge"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI.
-->
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<!--
Displays an Android View that continues showing the launch screen
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame.
-->
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="com.whatsapp.otp.OTP_RETRIEVED" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity> <!-- <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver" android:exported="true"> -->
</activity>
<!-- <receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver" android:exported="true">-->
<!-- <intent-filter>-->
<!-- <action android:name="android.intent.action.BOOT_COMPLETED"/>-->
<!-- <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<!-- Geofencing -->
<service
android:name=".geofence.intent_receivers.GeofenceTransitionsJobIntentService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<receiver
android:name=".geofence.intent_receivers.GeofenceBroadcastReceiver"
android:enabled="true"
android:exported="false" />
<receiver
android:name=".geofence.intent_receivers.GeofencingRebootBroadcastReceiver"
android:enabled="true"
android:exported="false">
<!-- Geofencing -->
<service android:name=".geofence.intent_receivers.GeofenceTransitionsJobIntentService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" />
<receiver android:name=".geofence.intent_receivers.GeofenceBroadcastReceiver" android:enabled="true" android:exported="false" />
<receiver android:name=".geofence.intent_receivers.GeofencingRebootBroadcastReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
</intent-filter>
</receiver>
<receiver
android:name=".geofence.intent_receivers.LocationProviderChangeReceiver"
android:exported="false">
<receiver android:name=".geofence.intent_receivers.LocationProviderChangeReceiver" android:exported="false">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED"/>
</intent-filter>
</receiver>
<service android:name=".geofence.intent_receivers.ReregisterGeofenceJobService" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- Geofencing -->
<service
android:name=".geofence.intent_receivers.ReregisterGeofenceJobService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" /> <!-- Geofencing -->
<!--
Huawei Push Notifications
Set push kit auto enable to true (for obtaining the token on initialize)
@ -221,9 +157,7 @@
<!-- android:name="push_kit_auto_init_enabled"-->
<!-- android:value="true" />-->
<!-- These receivers are for sending scheduled local notifications -->
<receiver
android:name="com.huawei.hms.flutter.push.receiver.local.HmsLocalNotificationBootEventReceiver"
android:exported="false">
<receiver android:name="com.huawei.hms.flutter.push.receiver.local.HmsLocalNotificationBootEventReceiver" android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
@ -239,17 +173,26 @@
<intent-filter>
<action android:name="com.huawei.hms.flutter.push.receiver.BACKGROUND_REMOTE_MESSAGE" />
</intent-filter>
</receiver> <!-- Huawei Push Notifications -->
<meta-data
android:name="com.google.android.geo.API_KEY"
</receiver>
<!-- Huawei Push Notifications -->
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyCyDbWUM9d_sBUGIE8PcuShzPaqO08NSC8"/>
<!--
Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java
-->
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
<!-- <uses-permission android:name="android.permission.INTERNET" />-->
<!-- <uses-permission android:name="android.permission.USE_FINGERPRINT" />-->
<!-- <uses-permission android:name="android.permission.READ_CALENDAR" />-->
<!-- <uses-permission android:name="android.permission.WRITE_CALENDAR" />-->
</manifest>

@ -1,5 +1,4 @@
package com.ejada.hmg
import android.app.PendingIntent
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
@ -8,7 +7,6 @@ import android.view.WindowManager
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi
import com.cloud.diplomaticquarterapp.PenguinInPlatformBridge
import com.cloud.diplomaticquarterapp.whatsapp.AppSignatureRetriever
import com.ejada.hmg.utils.*
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
@ -28,8 +26,11 @@ class MainActivity: FlutterFragmentActivity() {
OpenTokPlatformBridge(flutterEngine, this).create()
PenguinInPlatformBridge(flutterEngine, this).create()
WhatsAppOtpPlatformBridge(flutterEngine, this).invoke()
AppSignatureRetriever().logSignatures(this)
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {x
WhatsApp.handleOTP(intent){code ->
WhatsAppOtpPlatformBridge.result?.success(code);
}
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// val mChannel = NotificationChannel("video_call_noti", "video call", NotificationManager.IMPORTANCE_HIGH)
// val soundUri = Uri.parse("android.resource://" + getApplicationContext()
// .getPackageName() + "/" + R.raw.alert)

@ -1,81 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.cloud.diplomaticquarterapp.whatsapp;
import static java.sql.DriverManager.println;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
public class AppSignatureRetriever {
private static final String HASH_TYPE = "SHA-256";
public static final int NUM_HASHED_BYTES = 9;
public static final int NUM_BASE64_CHAR = 11;
public void logSignatures(Context context) {
Collection<String> appSignatures = getAppSignatures(context);
appSignatures.forEach(signature -> println("Signature: " + signature));
}
/**
* Get all the app signatures for the current package.
*
* @return signatures for current app
*/
public Collection<String> getAppSignatures(Context context) {
try {
// Get all package signatures for the current package
String packageName = context.getPackageName();
println("Package name: " + packageName);
PackageManager packageManager = context.getPackageManager();
Signature[] signatures = packageManager.getPackageInfo(packageName,
PackageManager.GET_SIGNATURES).signatures;
// For each signature create a compatible hash
Collection<String> appCodes = Arrays.stream(signatures)
.map(signature -> hash(packageName, signature.toCharsString()))
.collect(Collectors.toList());
return appCodes;
} catch (PackageManager.NameNotFoundException e) {
println("Unable to find package to obtain hash.");
throw new RuntimeException("Unable to find package to obtain hash.", e);
}
}
private String hash(String packageName, String signature) {
String appInfo = packageName + " " + signature;
try {
MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);
messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
byte[] hashSignature = messageDigest.digest();
// truncated into NUM_HASHED_BYTES
hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
// encode into Base64
String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);
println(String.format("pkg: %s -- hash: %s", packageName, base64Hash));
return base64Hash;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("Unable to generate hash for application", e);
}
}
}

@ -1,31 +0,0 @@
package com.cloud.diplomaticquarterapp.whatsapp
import android.content.Context
import android.content.Intent
import com.whatsapp.otp.android.sdk.WhatsAppOtpHandler
import com.whatsapp.otp.android.sdk.WhatsAppOtpIncomingIntentHandler
import java.lang.ref.WeakReference
object WhatsApp {
val whatsAppOtpHandler = WhatsAppOtpHandler()
inline fun handleOTP ( intent: Intent, crossinline validateOTP:(code: String )-> Unit) =
WhatsAppOtpIncomingIntentHandler().processOtpCode(
intent,
// call your function to validate
{code -> validateOTP(code) },
{error,exception->
println("the error is ${error.name}")
println("the exception stacktrace is ${exception.message}")
println("the exception is cause ${exception.cause}")
})
fun performHandShake(context : WeakReference<Context>) = whatsAppOtpHandler.sendOtpIntentToWhatsApp(context.get()!!)
fun isWhatsAppInstalled(context : WeakReference<Context>) : Boolean = whatsAppOtpHandler.isWhatsAppInstalled(context.get()!!)
}

@ -1,17 +0,0 @@
package com.ejada.hmg
import android.app.PendingIntent
import android.content.Intent
import android.os.Bundle
import com.cloud.diplomaticquarterapp.whatsapp.WhatsApp
import com.cloud.diplomaticquarterapp.whatsapp.WhatsAppOtpPlatformBridge
import io.flutter.embedding.android.FlutterFragmentActivity
class WhatsAppCodeActivity : FlutterFragmentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WhatsApp.handleOTP(intent){code ->
WhatsAppOtpPlatformBridge.result?.success(code);
finish()
}
}
}

@ -1,52 +0,0 @@
package com.cloud.diplomaticquarterapp.whatsapp
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.cloud.diplomaticquarterapp.penguin.PenguinView
import com.ejada.hmg.MainActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.lang.ref.WeakReference
class WhatsAppOtpPlatformBridge(
private var flutterEngine: FlutterEngine,
private var mainActivity: MainActivity
) {
private lateinit var channel: MethodChannel
companion object {
private const val CHANNEL = "whats_app_otp"
var result: MethodChannel.Result? = null
}
fun invoke() {
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
when (call.method) {
"isWhatsAppInstalled" -> {
val isAppInstalled =
WhatsApp.isWhatsAppInstalled(WeakReference(mainActivity))
result.success(isAppInstalled)
}
"performHandShake" -> {
WhatsApp.performHandShake(WeakReference(mainActivity))
}
"startListening" -> {
WhatsAppOtpPlatformBridge.result = result
}
else -> {
result.notImplemented()
}
}
}
}
}

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WhatsAppCodeActivity">
</androidx.constraintlayout.widget.ConstraintLayout>

@ -19,8 +19,8 @@ buildscript {
credentials {
username = 'mapbox'
password = "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
// password = "pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"
// password = "sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
password = "pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"
if (password == null || password == "") {
throw new GradleException("MAPBOX_DOWNLOADS_TOKEN isn't set. Set it to the project properties or to the enviroment variables.")
}
@ -37,12 +37,10 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
// classpath 'com.android.tools.build:gradle:8.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8'
// classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
classpath 'com.huawei.agconnect:agcp:1.5.2.300'
classpath("com.android.tools:r8:8.2.42")
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12'
classpath "com.mapbox.gradle.plugins:access-token:0.4.0"
}

@ -4,5 +4,5 @@ android.useAndroidX=true
android.enableJetifier=true
android.suppressUnsupportedCompileSdk=33
MAPBOX_USER_NAME = "mapbox"
MAPBOX_DOWNLOADS_TOKEN="sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
#MAPBOX_DOWNLOADS_TOKEN="pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"
#MAPBOX_DOWNLOADS_TOKEN="sk.eyJ1IjoicndhaWQiLCJhIjoiY2x6NWo0bTMzMWZodzJrcGZpemYzc3Z4dSJ9.uSSZuwNSGCcCdPAiORECmg"
MAPBOX_DOWNLOADS_TOKEN="pk.eyJ1IjoicndhaWQiLCJhIjoiY2x5cGo4aHNjMGNsbTJyc2djempobGQxaSJ9.RCaC6WrUt4A4YnZNfxnONQ"

@ -1,6 +1,4 @@
include ':app'
include ':vital-sign-engine'
project(':vital-sign-engine').projectDir = new File('/Users/mohamedmekawy/Documents/Work/DiplomaticQuarter_3.16/packages/vital_sign_camera/android/libs')
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -1,9 +0,0 @@
<svg id="route" xmlns="http://www.w3.org/2000/svg" width="27.521" height="27.521" viewBox="0 0 27.521 27.521">
<path id="Path_5246" data-name="Path 5246" d="M365.087,11.9a.806.806,0,0,0,1.457,0l2.916-6.138a4.034,4.034,0,1,0-7.288,0Zm.728-8.678a.806.806,0,1,1-.806.806A.806.806,0,0,1,365.815,3.225Z" transform="translate(-342.332)" fill="#28323a"/>
<ellipse id="Ellipse_225" data-name="Ellipse 225" cx="1.5" cy="1" rx="1.5" ry="1" transform="translate(14 21.522)" fill="#28323a"/>
<path id="Path_5247" data-name="Path 5247" d="M175.628,205.644a2.016,2.016,0,0,1,0-4.031h8.315L183.177,200h-7.549a3.628,3.628,0,0,0,0,7.257h4.537a3.235,3.235,0,0,1,0-1.613Z" transform="translate(-162.754 -189.249)" fill="#28323a"/>
<circle id="Ellipse_226" data-name="Ellipse 226" cx="1.5" cy="1.5" r="1.5" transform="translate(19 15.522)" fill="#28323a"/>
<path id="Path_5248" data-name="Path 5248" d="M350.39,305h-.183a3.236,3.236,0,0,1,0,1.613h.183a2.069,2.069,0,0,1,0,4.139H345.1a3.236,3.236,0,0,1,0,1.613h5.289a3.682,3.682,0,0,0,0-7.364Z" transform="translate(-326.551 -288.605)" fill="#28323a"/>
<path id="Path_5249" data-name="Path 5249" d="M167.02,412l.706,1.613h2.621a3.235,3.235,0,0,1,0-1.613Z" transform="translate(-158.042 -389.854)" fill="#28323a"/>
<path id="Path_5250" data-name="Path 5250" d="M5.311,322.415a.806.806,0,0,0-1.477,0l-3.763,8.6a.806.806,0,0,0,1.139,1.023l3.363-1.922,3.363,1.922a.806.806,0,0,0,1.139-1.023Z" transform="translate(0 -304.627)" fill="#28323a"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@ -1,3 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M27.2568 32L25.1631 30.6091C27.9468 26.2666 29.4463 21.2154 29.4998 15.9999C29.4463 10.7844 27.9468 5.73315 25.1631 1.39067L27.2568 0C30.304 4.75302 31.9441 10.2814 31.9998 15.9875L32 16.0001L31.9998 16.0128C31.9441 21.7186 30.304 27.247 27.2568 32ZM25.0625 16.0165L25.0627 15.9999L25.0625 15.983C25.0051 11.5525 23.6995 7.27342 21.2869 3.60788L19.2097 5.02439C21.3494 8.27467 22.5085 12.0694 22.5625 15.9999C22.5085 19.9301 21.3494 23.7248 19.2097 26.9751L21.2869 28.3916C23.6995 24.7263 25.0051 20.447 25.0625 16.0165ZM16.7007 22.9666C17.719 20.7477 18.2334 18.3302 18.188 15.9748C18.1284 12.8761 17.1565 9.86638 15.3779 7.27168L13.3276 8.72795C14.822 10.9081 15.6384 13.4313 15.6885 16.0247C15.7163 17.4783 15.4875 18.9644 15.0205 20.3943L1.56543 9.86414L0.925293 11.3547C0.887451 11.4427 0 13.5424 0 16.4452C0 19.4569 1.69165 22.1483 1.76367 22.2614L3.86157 20.8772C3.8479 20.8558 2.5 18.6766 2.5 16.4452C2.5 15.5068 2.61401 14.6693 2.75073 14.0018L16.0413 24.4033L16.7007 22.9666Z" fill="#2E303A"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1124.14 1256.39">
<defs>
<style>
.cls-1 {
fill: #231f20;
}
</style>
</defs>
<path class="cls-1" d="M699.62,1113.02h0c-20.06,44.48-33.32,92.75-38.4,143.37l424.51-90.24c20.06-44.47,33.31-92.75,38.4-143.37l-424.51,90.24Z"/>
<path class="cls-1" d="M1085.73,895.8c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.33v-135.2l292.27-62.11c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.27V66.13c-50.67,28.45-95.67,66.32-132.25,110.99v403.35l-132.25,28.11V0c-50.67,28.44-95.67,66.32-132.25,110.99v525.69l-295.91,62.88c-20.06,44.47-33.33,92.75-38.42,143.37l334.33-71.05v170.26l-358.3,76.14c-20.06,44.47-33.32,92.75-38.4,143.37l375.04-79.7c30.53-6.35,56.77-24.4,73.83-49.24l68.78-101.97v-.02c7.14-10.55,11.3-23.27,11.3-36.97v-149.98l132.25-28.11v270.4l424.53-90.28Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 923 B

@ -1,5 +0,0 @@
<svg id="Download" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
<path
class="color000000 svgShape"
d="M1344 1344q0-26-19-45t-45-19-45 19-19 45 19 45 45 19 45-19 19-45zm256 0q0-26-19-45t-45-19-45 19-19 45 19 45 45 19 45-19 19-45zm128-224v320q0 40-28 68t-68 28H160q-40 0-68-28t-28-68v-320q0-40 28-68t68-28h465l135 136q58 56 136 56t136-56l136-136h464q40 0 68 28t28 68zm-325-569q17 41-14 70l-448 448q-18 19-45 19t-45-19L403 621q-31-29-14-70 17-39 59-39h256V64q0-26 19-45t45-19h256q26 0 45 19t19 45v448h256q42 0 59 39z" fill="#ffffff"></path>
</svg>

Before

Width:  |  Height:  |  Size: 585 B

@ -1,3 +0,0 @@
<svg width="22" height="29" viewBox="0 0 22 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.5498 11.4402C17.4647 9.69433 20.0542 7.33316 20.2903 1.69231H22V0H0V1.69231H1.70974C1.94576 7.33316 4.53533 9.69433 6.45023 11.4402C7.73475 12.6113 8.46154 13.3281 8.46154 14.441C8.46154 15.5539 7.73475 16.2707 6.45023 17.4419C4.53533 19.1877 1.94576 21.5489 1.70974 27.1897H0V28.8821H22V27.1897H20.2903C20.0542 21.5489 17.4647 19.1877 15.5498 17.4419C14.2653 16.2707 13.5385 15.5539 13.5385 14.441C13.5385 13.3281 14.2653 12.6113 15.5498 11.4402ZM10.1538 20.7837C9.8925 20.8376 9.63431 20.9161 9.38232 21.0203L4.19952 23.165C5.0459 21.0129 6.40911 19.7695 7.5904 18.6925C8.9087 17.4906 10.1538 16.3553 10.1538 14.441V20.7837ZM14.4096 18.6925C15.5909 19.7695 16.954 21.0129 17.8005 23.1649L12.6177 21.0203C12.3657 20.916 12.1075 20.8376 11.8462 20.7836V14.441C11.8462 16.3553 13.0913 17.4906 14.4096 18.6925ZM4.16979 5.64103C3.76065 4.57493 3.47809 3.2877 3.40413 1.69231H18.5958C18.5219 3.2877 18.2394 4.57493 17.8302 5.64103H4.16979Z" fill="#2E303A"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

@ -1,11 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31">
<g id="route" transform="translate(0 0)">
<path id="Path_5246" data-name="Path 5246" d="M365.505,13.407a.908.908,0,0,0,1.641,0l3.284-6.914a4.544,4.544,0,1,0-8.209,0Zm.82-9.774a.908.908,0,1,1-.908.908A.908.908,0,0,1,366.326,3.633Z" transform="translate(-339.874)" fill="#da4a54"/>
<circle id="Ellipse_225" data-name="Ellipse 225" cx="1.5" cy="1.5" r="1.5" transform="translate(16 24)" fill="#2e303a"/>
<path id="Path_5247" data-name="Path 5247" d="M176.087,206.357a2.27,2.27,0,0,1,0-4.541h9.366L184.59,200h-8.5a4.087,4.087,0,0,0,0,8.174h5.11a3.644,3.644,0,0,1,0-1.816Z" transform="translate(-161.586 -187.891)" fill="#2e303a"/>
<circle id="Ellipse_226" data-name="Ellipse 226" cx="2" cy="2" r="2" transform="translate(21 17)" fill="#2e303a"/>
<path id="Path_5248" data-name="Path 5248" d="M351.059,305h-.206a3.644,3.644,0,0,1,0,1.816h.206a2.331,2.331,0,0,1,0,4.662H345.1a3.645,3.645,0,0,1,0,1.816h5.958a4.147,4.147,0,0,0,0-8.295Z" transform="translate(-324.206 -286.533)" fill="#2e303a"/>
<path id="Path_5249" data-name="Path 5249" d="M167.02,412l.795,1.816h2.952a3.644,3.644,0,0,1,0-1.816Z" transform="translate(-156.907 -387.055)" fill="#2e303a"/>
<path id="Path_5250" data-name="Path 5250" d="M5.982,322.476a.908.908,0,0,0-1.664,0L.08,332.164a.908.908,0,0,0,1.283,1.153l3.788-2.164,3.788,2.164a.908.908,0,0,0,1.283-1.153Z" transform="translate(0 -302.44)" fill="#2e303a"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@ -1,3 +0,0 @@
<svg width="23" height="29" viewBox="0 0 23 29" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19.2821 9.01172C18.9238 9.01172 18.5814 9.08629 18.2671 9.22183C17.9481 7.9542 16.8772 7.01953 15.6088 7.01953C14.9039 7.01953 14.2599 7.3082 13.7722 7.78227C13.2844 7.3082 12.6405 7.01953 11.9356 7.01953C11.6137 7.01953 11.3046 7.0797 11.0173 7.1902V3.96484C11.0173 2.31711 9.78138 0.976562 8.2623 0.976562C6.74323 0.976562 5.50736 2.31711 5.50736 3.96484V12.7547C5.06406 12.2739 4.70028 11.8793 4.70028 11.8793C3.68187 10.7746 2.03312 10.7115 0.9489 11.7334C-0.14065 12.7546 -0.316355 14.5345 0.548882 15.7856C0.558678 15.7998 0.568841 15.8136 0.57937 15.8272L4.66385 21.1185C5.1074 21.6931 5.74741 22.0491 6.31205 22.3632C6.72296 22.5918 7.34399 22.9373 7.34399 23.1565V26.0117C7.34399 27.6595 8.57986 29 10.0989 29H17.4455C18.9645 29 20.2004 27.6595 20.2004 26.0117V23.9531C20.2004 23.5591 20.5492 23.0843 20.9185 22.5818C21.4428 21.8683 22.037 21.0596 22.037 19.9688V12C22.037 10.3523 20.8012 9.01172 19.2821 9.01172ZM19.4823 21.3401C18.958 22.0536 18.3638 22.8623 18.3638 23.9531V26.0117C18.3638 26.561 17.9518 27.0078 17.4455 27.0078H10.0989C9.59258 27.0078 9.18062 26.561 9.18062 26.0117V23.1564C9.18062 21.72 8.00707 21.0672 7.1501 20.5904C6.72064 20.3515 6.2766 20.1046 6.072 19.8395L2.006 14.572C1.73131 14.1561 1.79259 13.5755 2.15165 13.2389C2.51304 12.8982 3.06213 12.9197 3.4016 13.2879C3.4016 13.2879 5.62662 15.7015 5.77685 15.8641C6.35294 16.4878 7.34393 16.0456 7.34393 15.1591V3.96484C7.34393 3.4156 7.75588 2.96875 8.26224 2.96875C8.7686 2.96875 9.18056 3.4156 9.18056 3.96484V12C9.18056 12.5501 9.59172 12.9961 10.0989 12.9961C10.606 12.9961 11.0172 12.5501 11.0172 12V10.0078C11.0172 9.45857 11.4291 9.01172 11.9355 9.01172C12.4419 9.01172 12.8538 9.45857 12.8538 10.0078V12C12.8538 12.5501 13.265 12.9961 13.7721 12.9961C14.2793 12.9961 14.6905 12.5501 14.6905 12V10.0078C14.6905 9.45857 15.1024 9.01172 15.6088 9.01172C16.1151 9.01172 16.5271 9.45857 16.5271 10.0078V12C16.5271 12.5501 16.9382 12.9961 17.4454 12.9961C17.9526 12.9961 18.3637 12.5501 18.3637 12C18.3637 11.4508 18.7757 11.0039 19.282 11.0039C19.7884 11.0039 20.2003 11.4508 20.2003 12V19.9688H20.2004C20.2004 20.3628 19.8516 20.8375 19.4823 21.3401Z" fill="#2E303A"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@ -1,6 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="31" height="31" viewBox="0 0 31 31">
<g id="Group_8325" data-name="Group 8325" transform="translate(-75 -236)">
<circle id="Ellipse_223" data-name="Ellipse 223" cx="15.5" cy="15.5" r="15.5" transform="translate(75 236)" fill="#359846"/>
<path id="hour-glass" d="M8.73,10.811a1.46,1.46,0,0,0,0-2.122L8.647,8.61C7.085,7.119,5.878,5.968,5.515,3.556A1.413,1.413,0,0,1,6.992,2h7.091A1.413,1.413,0,0,1,15.56,3.556C15.2,5.968,13.99,7.119,12.429,8.61l-.083.079a1.46,1.46,0,0,0,0,2.122l.083.079c1.562,1.491,2.768,2.642,3.132,5.054A1.413,1.413,0,0,1,14.083,17.5H6.992a1.413,1.413,0,0,1-1.477-1.556c.364-2.412,1.57-3.563,3.132-5.054Zm.529,1.316-.006,0c-1.19,1.064-2.076,1.856-2.191,3.816a.363.363,0,0,0,.13.3.382.382,0,0,0,.247.09h6.194a.382.382,0,0,0,.282-.122.361.361,0,0,0,.1-.268c-.115-1.959-1-2.752-2.191-3.816-.315-.281-.651-.582-1-.928a.4.4,0,0,0-.569,0c-.347.344-.681.643-.993.923Z" transform="translate(80.35 241.75)" fill="#fff" fill-rule="evenodd"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1021 B

@ -33,8 +33,7 @@ target 'Runner' do
pod 'OpenTok', '~> 2.22.0'
pod 'VTO2Lib'
pod 'MapboxMaps', '10.19.0'
pod 'MapboxNavigation', '2.19.0'
pod 'MapboxMaps', '10.18.2'
pod 'FLAnimatedImage'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

@ -14,16 +14,15 @@
306FE6C8271D790C002D6EFC /* OpenTokPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */; };
306FE6CB271D8B73002D6EFC /* OpenTok.swift in Sources */ = {isa = PBXBuildFile; fileRef = 306FE6CA271D8B73002D6EFC /* OpenTok.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
55DE18989C1F69DC483B9FB6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C56AF9B31AA04A5292EEA39F /* Pods_Runner.framework */; };
47C935002C91766800981BA7 /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FC2C91766400981BA7 /* Penguin.xcframework */; };
47C935012C91766800981BA7 /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FC2C91766400981BA7 /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
47C935022C91766900981BA7 /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */; };
47C935032C91766900981BA7 /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
47C935042C91766A00981BA7 /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */; };
47C935052C91766A00981BA7 /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 47C934FB2C91766400981BA7 /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
762D738E274E42650063CE73 /* ring_30Sec.caf in Resources */ = {isa = PBXBuildFile; fileRef = 762D738C274E42650063CE73 /* ring_30Sec.caf */; };
762D738F274E42650063CE73 /* ring_30Sec.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 762D738D274E42650063CE73 /* ring_30Sec.mp3 */; };
7651B82F2D3E9CA40066B33A /* PenguinINRenderer.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82C2D3E9CA40066B33A /* PenguinINRenderer.xcframework */; };
7651B8302D3E9CA40066B33A /* PenguinINRenderer.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82C2D3E9CA40066B33A /* PenguinINRenderer.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
7651B8312D3E9CA40066B33A /* Penguin.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82D2D3E9CA40066B33A /* Penguin.xcframework */; };
7651B8322D3E9CA40066B33A /* Penguin.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82D2D3E9CA40066B33A /* Penguin.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
7651B8332D3E9CA40066B33A /* PenNavUI.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82E2D3E9CA40066B33A /* PenNavUI.xcframework */; };
7651B8342D3E9CA40066B33A /* PenNavUI.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7651B82E2D3E9CA40066B33A /* PenNavUI.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
76815B27275F381C00E66E94 /* HealthKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76815B26275F381C00E66E94 /* HealthKit.framework */; };
76962ECE28AE5C10004EAE09 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 76962ECD28AE5C10004EAE09 /* GoogleService-Info.plist */; };
76D71B672C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76D71B662C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift */; };
@ -52,18 +51,19 @@
E9C8C136256BACDA00EFFB62 /* HMG_Guest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */; };
E9E27168256E3A4000F49B69 /* LocalizedFromFlutter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */; };
E9F7623B25922BCE00FB5CCF /* FlutterConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */; };
FD7241B0D73FB24C87572FAC /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E413842321D0D624872E9BE /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
7651B8352D3E9CA50066B33A /* Embed Frameworks */ = {
768D81742C6DF6E4005C655F /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
7651B8322D3E9CA40066B33A /* Penguin.xcframework in Embed Frameworks */,
7651B8302D3E9CA40066B33A /* PenguinINRenderer.xcframework in Embed Frameworks */,
7651B8342D3E9CA40066B33A /* PenNavUI.xcframework in Embed Frameworks */,
47C935032C91766900981BA7 /* PenguinINRenderer.xcframework in Embed Frameworks */,
47C935012C91766800981BA7 /* Penguin.xcframework in Embed Frameworks */,
47C935052C91766A00981BA7 /* PenNavUI.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -71,7 +71,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
02C0468611167F0E858967A9 /* 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>"; };
29631B9D2C96C7F600DF5916 /* PenguinNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinNavigator.swift; sourceTree = "<group>"; };
@ -80,6 +79,10 @@
306FE6C7271D790C002D6EFC /* OpenTokPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTokPlatformBridge.swift; sourceTree = "<group>"; };
306FE6CA271D8B73002D6EFC /* OpenTok.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenTok.swift; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = "<group>"; };
47C934FB2C91766400981BA7 /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = "<group>"; };
47C934FC2C91766400981BA7 /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = "<group>"; };
6EE8819867EC2775AB578377 /* 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>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
762D738C274E42650063CE73 /* ring_30Sec.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = ring_30Sec.caf; path = ../../assets/sounds/ring_30Sec.caf; sourceTree = "<group>"; };
@ -87,9 +90,6 @@
7643E4042BE0D0B400BD2F25 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Main_Custom.strings; sourceTree = "<group>"; };
7643E4052BE0D0B400BD2F25 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Main.strings; sourceTree = "<group>"; };
7643E4062BE0D0B400BD2F25 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LaunchScreen.strings; sourceTree = "<group>"; };
7651B82C2D3E9CA40066B33A /* PenguinINRenderer.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenguinINRenderer.xcframework; path = Frameworks/PenguinINRenderer.xcframework; sourceTree = "<group>"; };
7651B82D2D3E9CA40066B33A /* Penguin.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Penguin.xcframework; path = Frameworks/Penguin.xcframework; sourceTree = "<group>"; };
7651B82E2D3E9CA40066B33A /* PenNavUI.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PenNavUI.xcframework; path = Frameworks/PenNavUI.xcframework; sourceTree = "<group>"; };
76815B26275F381C00E66E94 /* HealthKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HealthKit.framework; path = System/Library/Frameworks/HealthKit.framework; sourceTree = SDKROOT; };
76962ECD28AE5C10004EAE09 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
76D71B662C6B7F9C00DAFB84 /* HMGPenguinInPlatformBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HMGPenguinInPlatformBridge.swift; sourceTree = "<group>"; };
@ -99,6 +99,8 @@
76D71B6F2C6B81EA00DAFB84 /* PenguinViewFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenguinViewFactory.swift; sourceTree = "<group>"; };
76F2556027F1FFED0062C1CD /* PassKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PassKit.framework; path = System/Library/Frameworks/PassKit.framework; sourceTree = SDKROOT; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
838788A2BEDC4910F4B029A6 /* 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>"; };
8E413842321D0D624872E9BE /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<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; };
@ -106,9 +108,6 @@
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>"; };
9E4A8F0312C6AED5D3DC152C /* 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>"; };
C56AF9B31AA04A5292EEA39F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D72A14381E2E5999FC41D0A8 /* 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>"; };
E91B538D256AAA6500E96549 /* GlobalHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GlobalHelper.swift; sourceTree = "<group>"; };
E91B538E256AAA6500E96549 /* Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
E91B538F256AAA6500E96549 /* API.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = "<group>"; };
@ -127,6 +126,7 @@
E9C8C135256BACDA00EFFB62 /* HMG_Guest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HMG_Guest.swift; sourceTree = "<group>"; };
E9E27167256E3A4000F49B69 /* LocalizedFromFlutter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedFromFlutter.swift; sourceTree = "<group>"; };
E9F7623A25922BCE00FB5CCF /* FlutterConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlutterConstants.swift; sourceTree = "<group>"; };
F2C7D3C4718A1DED85DA3AD4 /* 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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -134,13 +134,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7651B8312D3E9CA40066B33A /* Penguin.xcframework in Frameworks */,
76F2556127F1FFED0062C1CD /* PassKit.framework in Frameworks */,
76815B27275F381C00E66E94 /* HealthKit.framework in Frameworks */,
E9620805255C2ED100D3A35D /* NetworkExtension.framework in Frameworks */,
7651B8332D3E9CA40066B33A /* PenNavUI.xcframework in Frameworks */,
7651B82F2D3E9CA40066B33A /* PenguinINRenderer.xcframework in Frameworks */,
55DE18989C1F69DC483B9FB6 /* Pods_Runner.framework in Frameworks */,
47C935042C91766A00981BA7 /* PenNavUI.xcframework in Frameworks */,
47C935002C91766800981BA7 /* Penguin.xcframework in Frameworks */,
47C935022C91766900981BA7 /* PenguinINRenderer.xcframework in Frameworks */,
FD7241B0D73FB24C87572FAC /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -160,13 +160,13 @@
555EAAA626EFB641859EF0BE /* Frameworks */ = {
isa = PBXGroup;
children = (
7651B82D2D3E9CA40066B33A /* Penguin.xcframework */,
7651B82C2D3E9CA40066B33A /* PenguinINRenderer.xcframework */,
7651B82E2D3E9CA40066B33A /* PenNavUI.xcframework */,
47C934FC2C91766400981BA7 /* Penguin.xcframework */,
47C934FA2C91766400981BA7 /* PenguinINRenderer.xcframework */,
47C934FB2C91766400981BA7 /* PenNavUI.xcframework */,
76F2556027F1FFED0062C1CD /* PassKit.framework */,
76815B26275F381C00E66E94 /* HealthKit.framework */,
E9620804255C2ED100D3A35D /* NetworkExtension.framework */,
C56AF9B31AA04A5292EEA39F /* Pods_Runner.framework */,
8E413842321D0D624872E9BE /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -174,9 +174,9 @@
605039E5DDF72C245F9765FE /* Pods */ = {
isa = PBXGroup;
children = (
D72A14381E2E5999FC41D0A8 /* Pods-Runner.debug.xcconfig */,
02C0468611167F0E858967A9 /* Pods-Runner.release.xcconfig */,
9E4A8F0312C6AED5D3DC152C /* Pods-Runner.profile.xcconfig */,
F2C7D3C4718A1DED85DA3AD4 /* Pods-Runner.debug.xcconfig */,
838788A2BEDC4910F4B029A6 /* Pods-Runner.release.xcconfig */,
6EE8819867EC2775AB578377 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -293,15 +293,15 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
BEE88E0BBD555ACCD7E82B57 /* [CP] Check Pods Manifest.lock */,
6D0B2FE51DC05E2D0395E861 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
7651B8352D3E9CA50066B33A /* Embed Frameworks */,
768D81742C6DF6E4005C655F /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
191312D8478950EB12CBDD28 /* [CP] Embed Pods Frameworks */,
4CC68CB45B720A365C7CF7DC /* [CP] Copy Pods Resources */,
487FDD6493EB9AE7D8E39485 /* [CP] Embed Pods Frameworks */,
4671D3CD126F6635F4B75A6E /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -368,23 +368,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
191312D8478950EB12CBDD28 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
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 = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
@ -401,7 +384,7 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
};
4CC68CB45B720A365C7CF7DC /* [CP] Copy Pods Resources */ = {
4671D3CD126F6635F4B75A6E /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -418,22 +401,24 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
487FDD6493EB9AE7D8E39485 /* [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\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
BEE88E0BBD555ACCD7E82B57 /* [CP] Check Pods Manifest.lock */ = {
6D0B2FE51DC05E2D0395E861 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -455,6 +440,21 @@
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;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -589,7 +589,6 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(SRCROOT)/Frameworks",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -601,7 +600,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.6.004;
MARKETING_VERSION = 4.5.998;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -741,7 +740,6 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(SRCROOT)/Frameworks",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -753,7 +751,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.6.004;
MARKETING_VERSION = 4.5.998;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@ -785,7 +783,6 @@
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(SRCROOT)/Frameworks",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -797,7 +794,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 4.6.004;
MARKETING_VERSION = 4.5.998;
PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

@ -697,13 +697,15 @@ var GET_PATIENT_OCCUPATION_LIST = 'Services/Authentication.svc/REST/GetPatientOc
var IS_DOCTOR_AVAILABLE_BY_CALENDAR_SCHEDULE = 'Services/OUTPs.svc/REST/HIS_IsDoctorAvailableByCalendarSchedule';
var GET_PATIENT_LAB_QUEUE_NUMBER = 'Services/Doctors.svc/REST/LabPatientCallNoGetQline';
//PAYFORT
var getPayFortProjectDetails = "Services/PayFort_Serv.svc/REST/GetPayFortProjectDetails";
var addPayFortApplePayResponse = "Services/PayFort_Serv.svc/REST/AddResponse";
var payFortEnvironment = FortEnvironment.production;
var applePayMerchantId = "merchant.com.hmgwebservices";
// var payFortEnvironment = FortEnvironment.test;
// var applePayMerchantId = "merchant.com.hmgwebservices.uat";
// var payFortEnvironment = FortEnvironment.production;
// var applePayMerchantId = "merchant.com.hmgwebservices";
var payFortEnvironment = FortEnvironment.test;
var applePayMerchantId = "merchant.com.hmgwebservices.uat";
class AppGlobal {
static var context;

@ -586,7 +586,6 @@ const Map localizedValues = {
"items": {"en": "item(s)", "ar": "عنصر"},
"checkOut": {"en": "CHECK OUT", "ar": "الدفع"},
"sar": {"en": "SAR", "ar": " ر.س "},
// "sar": {"en": "", "ar": ""},
"aed": {"en": "AED", "ar": "درهم"},
"payOnline": {"en": "PAY ONLINE", "ar": "اتمام عملية الدفع "},
"cancelOrder": {"en": "CANCEL ORDER", "ar": "الغاء الطلب "},
@ -1801,7 +1800,8 @@ const Map localizedValues = {
"ancillaryOrdersPaymentConfirm": {"en": "Are you sure you want to make payment for selected orders?", "ar": "هل أنت متأكد أنك تريد سداد قيمة الطلبات المختارة؟"},
"successRegister": {"en": "Your account has been created.", "ar": "لقد تم إنشاء حسابك."},
"pharmacyLiveCare": {"en": "Pharmacy LiveCare", "ar": "لايف كير صيدلية"},
"ancillaryOrderPaymentSuccess": {"en": "Your payment for selected orders has been made successfully.", "ar": "تم سداد دفعتك للطلبات المحددة بنجاح."},
"ancillaryOrderPaymentSuccess": {"en": "Your payment for selected orders has been made successfully. Please Check-In once you arrive into the hospital.", "ar": "لقد تم الدفع بنجاح للطلبات المحددة. يرجى تسجيل الدخول بمجرد وصولك إلى المستشفى.."},
"ancillaryOrderCheckInSuccess": {"en": "Your Check-In for selected ancillary order has been done successfully. Please proceed to the waiting area. Your Queue No. is: ", "ar": "لقد تم تسجيل وصولك بنجاح للطلب الإضافي المحدد. يرجى الانتقال إلى منطقة الانتظار. رقم صف الانتظار الخاص بك هو: "},
"connectTitle": {"en": "Connect", "ar": "تواصل"},
"connectSubtitle": {"en": "With us", "ar": "معنا"},
"covidConsent": {

@ -187,7 +187,7 @@ class BaseAppClient {
// body['IdentificationNo'] = 1023854217;
// body['MobileNo'] = "531940021"; //0560717232
// body['PatientID'] = 2007395; //4609100
// body['PatientID'] = 1058229; //4609100
// body['TokenID'] = "@dm!n";
// Patient ID: 3027574

@ -29,25 +29,6 @@ class AskDoctorService extends BaseService {
return Future.value(localRes);
}
Future isDoctorAvailable({int? projectId, int? doctorId, int? clinicId}) async {
hasError = false;
Map<String, dynamic> body = Map();
body['isDentalAllowedBackend'] = false;
body['DoctorID'] = doctorId;
body['ProjectID'] = projectId;
body['ClinicID'] = clinicId;
dynamic localRes;
await baseAppClient.post(IS_DOCTOR_AVAILABLE_BY_CALENDAR_SCHEDULE, onSuccess: (dynamic response, int statusCode) {
localRes = response;
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
}, body: body);
return Future.value(localRes);
}
Future getCallRequestTypeLOV() async {
hasError = false;
Map<String, dynamic> body = Map();

@ -42,7 +42,7 @@ class LabsService extends BaseService {
_requestPatientLabSpecialResult.invoiceNo = isVidaPlus! ? "0" : invoiceNo;
_requestPatientLabSpecialResult.invoiceNoVP = isVidaPlus ? invoiceNo : "0";
_requestPatientLabSpecialResult.invoiceType = invoiceType ?? "";
_requestPatientLabSpecialResult.invoiceType = invoiceType!;
_requestPatientLabSpecialResult.orderNo = orderNo;
_requestPatientLabSpecialResult.setupID = setupID;
@ -209,7 +209,7 @@ class LabsService extends BaseService {
RequestSendLabReportEmail _requestSendLabReportEmail = RequestSendLabReportEmail();
Future sendLabReportEmail({PatientLabOrders? patientLabOrder, AuthenticatedUser? userObj, bool isVidaPlus = false, bool isDownload = false, int languageID = 1}) async {
Future sendLabReportEmail({PatientLabOrders? patientLabOrder, AuthenticatedUser? userObj, bool isVidaPlus = false, bool isDownload = false}) async {
_requestSendLabReportEmail.projectID = patientLabOrder!.projectID;
_requestSendLabReportEmail.invoiceNo = isVidaPlus ? "0" : patientLabOrder.invoiceNo;
_requestSendLabReportEmail.invoiceNoVP = isVidaPlus ? patientLabOrder.invoiceNo : "0";
@ -228,12 +228,11 @@ class LabsService extends BaseService {
_requestSendLabReportEmail.orderNo = patientLabOrder.orderNo;
_requestSendLabReportEmail.isDownload = isDownload;
_requestSendLabReportEmail.doctorID = patientLabOrder.doctorID;
_requestSendLabReportEmail.languageID = languageID;
_requestSendLabReportEmail.languageID = 1;
// await baseAppClient.post(SEND_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) {
await baseAppClient.post(isVidaPlus ? SEND_LAB_RESULT_EMAIL : SEND_LAB_RESULT_EMAIL_NEW, onSuccess: (dynamic response, int statusCode) {
await baseAppClient.post(SEND_LAB_RESULT_EMAIL, onSuccess: (dynamic response, int statusCode) {
if (isDownload) {
labReportPDF = isVidaPlus ? response['LabReportsPDFContent'] : response['PdfContent'];
labReportPDF = response['LabReportsPDFContent'];
}
}, onFailure: (String error, int statusCode) {
hasError = true;

@ -1,7 +1,3 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:diplomaticquarterapp/core/enum/filter_type.dart';
import 'package:diplomaticquarterapp/core/enum/viewstate.dart';
import 'package:diplomaticquarterapp/core/model/labs/LabOrderResult.dart';
@ -13,8 +9,6 @@ import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.da
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/widgets/charts/app_time_series_chart.dart';
import 'package:open_filex/open_filex.dart';
import 'package:path_provider/path_provider.dart';
import '../../../locator.dart';
import '../base_view_model.dart';
@ -82,7 +76,13 @@ class LabsViewModel extends BaseViewModel {
getLaboratoryResult({String? projectID, int? clinicID, String? invoiceNo, String? invoiceType, String? orderNo, String? setupID, bool? isVidaPlus}) async {
setState(ViewState.Busy);
await _labsService.getLaboratoryResult(invoiceNo: invoiceNo, invoiceType: invoiceType, orderNo: orderNo, projectID: projectID, clinicID: clinicID, setupID: setupID, isVidaPlus: isVidaPlus);
await _labsService.getLaboratoryResult(invoiceNo: invoiceNo,
invoiceType: invoiceType,
orderNo: orderNo,
projectID: projectID,
clinicID: clinicID,
setupID: setupID,
isVidaPlus: isVidaPlus);
if (_labsService.hasError) {
error = _labsService.error!;
setState(ViewState.Error);
@ -150,31 +150,15 @@ class LabsViewModel extends BaseViewModel {
}
}
sendLabReportEmail({PatientLabOrders? patientLabOrder, String? mes, AuthenticatedUser? userObj, required bool isVidaPlus, bool isDownload = false, int languageID = 1}) async {
await _labsService.sendLabReportEmail(patientLabOrder: patientLabOrder, userObj: userObj, isVidaPlus: isVidaPlus, isDownload: isDownload, languageID: languageID);
sendLabReportEmail({PatientLabOrders? patientLabOrder, String? mes, AuthenticatedUser? userObj, required bool isVidaPlus, bool isDownload = false}) async {
await _labsService.sendLabReportEmail(patientLabOrder: patientLabOrder, userObj: userObj, isVidaPlus: isVidaPlus, isDownload: isDownload);
if (_labsService.hasError) {
error = _labsService.error!;
} else {
if (isDownload) {
if (labReportPDF.isNotEmpty) {
String path = await _createFileFromString(labReportPDF, "pdf");
try {
OpenFilex.open(path);
} catch (ex) {
AppToast.showErrorToast(message: "Cannot open file.");
}
}
} else {
AppToast.showSuccessToast(message: mes!);
}
}
}
Future<String> _createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
}

@ -24,7 +24,7 @@ class AncillaryOrdersListModel {
AncillaryOrdersListModel.fromJson(Map<String, dynamic> json) {
if (json['AncillaryOrderList'] != null) {
ancillaryOrderList =[];
ancillaryOrderList = <AncillaryOrderList>[];
json['AncillaryOrderList'].forEach((v) {
ancillaryOrderList!.add(new AncillaryOrderList.fromJson(v));
});
@ -32,7 +32,7 @@ class AncillaryOrdersListModel {
errCode = json['ErrCode'];
message = json['Message'];
patientID = json['PatientID'];
patientName = json['PatientName'] != null ? json['PatientName'] : "";
patientName = json['PatientName'];
patientType = json['PatientType'];
projectID = json['ProjectID'];
projectName = json['ProjectName'];
@ -60,46 +60,228 @@ class AncillaryOrdersListModel {
}
class AncillaryOrderList {
List<AncillaryProcedureListModels>? ancillaryProcedureListModels;
String? appointmentDate;
int? appointmentNo;
int? clinicID;
String? clinicName;
int? doctorID;
String? doctorName;
bool? isCheckInAllow;
bool? isQueued;
String? orderDate;
int? orderNo;
int? invoiceNo;
AncillaryOrderList(
{this.appointmentDate,
{this.ancillaryProcedureListModels,
this.appointmentDate,
this.appointmentNo,
this.clinicID,
this.clinicName,
this.doctorID,
this.doctorName,
this.isCheckInAllow,
this.isQueued,
this.orderDate,
this.orderNo});
this.orderNo,
this.invoiceNo});
AncillaryOrderList.fromJson(Map<String, dynamic> json) {
if (json['AncillaryProcedureListModels'] != null) {
ancillaryProcedureListModels = <AncillaryProcedureListModels>[];
json['AncillaryProcedureListModels'].forEach((v) {
ancillaryProcedureListModels!
.add(new AncillaryProcedureListModels.fromJson(v));
});
}
appointmentDate = json['AppointmentDate'];
appointmentNo = json['AppointmentNo'];
clinicID = json['ClinicID'];
clinicName = json['ClinicName'] != null ? json['ClinicName'] : "";
clinicName = json['ClinicName'];
doctorID = json['DoctorID'];
doctorName = json['DoctorName'];
isCheckInAllow = json['IsCheckInAllow'];
isQueued = json['IsQueued'];
orderDate = json['OrderDate'];
orderNo = json['OrderNo'];
invoiceNo = json['Invoiceno'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.ancillaryProcedureListModels != null) {
data['AncillaryProcedureListModels'] =
this.ancillaryProcedureListModels!.map((v) => v.toJson()).toList();
}
data['AppointmentDate'] = this.appointmentDate;
data['AppointmentNo'] = this.appointmentNo;
data['ClinicID'] = this.clinicID;
data['ClinicName'] = this.clinicName;
data['DoctorID'] = this.doctorID;
data['DoctorName'] = this.doctorName;
data['IsCheckInAllow'] = this.isCheckInAllow;
data['IsQueued'] = this.isQueued;
data['OrderDate'] = this.orderDate;
data['OrderNo'] = this.orderNo;
data['Invoiceno'] = this.invoiceNo;
return data;
}
}
class AncillaryProcedureListModels {
int? ancillaryProcedureId;
int? appointmentNo;
int? approvalLineItemNo;
int? createdBy;
String? createdOn;
int? editedBy;
String? editedOn;
bool? isActive;
int? orderLineItemNo;
int? orderNo;
int? patientID;
String? procedureID;
int? projectID;
AncillaryProcedureListModels(
{this.ancillaryProcedureId,
this.appointmentNo,
this.approvalLineItemNo,
this.createdBy,
this.createdOn,
this.editedBy,
this.editedOn,
this.isActive,
this.orderLineItemNo,
this.orderNo,
this.patientID,
this.procedureID,
this.projectID});
AncillaryProcedureListModels.fromJson(Map<String, dynamic> json) {
ancillaryProcedureId = json['AncillaryProcedureId'];
appointmentNo = json['AppointmentNo'];
approvalLineItemNo = json['ApprovalLineItemNo'];
createdBy = json['CreatedBy'];
createdOn = json['CreatedOn'];
editedBy = json['EditedBy'];
editedOn = json['EditedOn'];
isActive = json['IsActive'];
orderLineItemNo = json['OrderLineItemNo'];
orderNo = json['OrderNo'];
patientID = json['PatientID'];
procedureID = json['ProcedureID'];
projectID = json['ProjectID'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['AncillaryProcedureId'] = this.ancillaryProcedureId;
data['AppointmentNo'] = this.appointmentNo;
data['ApprovalLineItemNo'] = this.approvalLineItemNo;
data['CreatedBy'] = this.createdBy;
data['CreatedOn'] = this.createdOn;
data['EditedBy'] = this.editedBy;
data['EditedOn'] = this.editedOn;
data['IsActive'] = this.isActive;
data['OrderLineItemNo'] = this.orderLineItemNo;
data['OrderNo'] = this.orderNo;
data['PatientID'] = this.patientID;
data['ProcedureID'] = this.procedureID;
data['ProjectID'] = this.projectID;
return data;
}
}
// class AncillaryOrdersListModel {
// List<AncillaryOrderList>? ancillaryOrderList;
// dynamic errCode;
// String? message;
// int? patientID;
// String? patientName;
// int? patientType;
// int? projectID;
// String? projectName;
// String? setupID;
// int? statusCode;
//
// AncillaryOrdersListModel({this.ancillaryOrderList, this.errCode, this.message, this.patientID, this.patientName, this.patientType, this.projectID, this.projectName, this.setupID, this.statusCode});
//
// AncillaryOrdersListModel.fromJson(Map<String, dynamic> json) {
// if (json['AncillaryOrderList'] != null) {
// ancillaryOrderList = [];
// json['AncillaryOrderList'].forEach((v) {
// ancillaryOrderList!.add(new AncillaryOrderList.fromJson(v));
// });
// }
// errCode = json['ErrCode'];
// message = json['Message'];
// patientID = json['PatientID'];
// patientName = json['PatientName'] != null ? json['PatientName'] : "";
// patientType = json['PatientType'];
// projectID = json['ProjectID'];
// projectName = json['ProjectName'];
// setupID = json['SetupID'];
// statusCode = json['StatusCode'];
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// if (this.ancillaryOrderList != null) {
// data['AncillaryOrderList'] = this.ancillaryOrderList!.map((v) => v.toJson()).toList();
// }
// data['ErrCode'] = this.errCode;
// data['Message'] = this.message;
// data['PatientID'] = this.patientID;
// data['PatientName'] = this.patientName;
// data['PatientType'] = this.patientType;
// data['ProjectID'] = this.projectID;
// data['ProjectName'] = this.projectName;
// data['SetupID'] = this.setupID;
// data['StatusCode'] = this.statusCode;
// return data;
// }
// }
//
// class AncillaryOrderList {
// String? appointmentDate;
// int? appointmentNo;
// int? clinicID;
// String? clinicName;
// int? doctorID;
// String? doctorName;
// String? orderDate;
// int? orderNo;
// bool? isAllowCheckIn;
// String? procedureIDs;
//
// AncillaryOrderList({this.appointmentDate, this.appointmentNo, this.clinicID, this.clinicName, this.doctorID, this.doctorName, this.orderDate, this.orderNo, this.isAllowCheckIn, this.procedureIDs});
//
// AncillaryOrderList.fromJson(Map<String, dynamic> json) {
// appointmentDate = json['AppointmentDate'];
// appointmentNo = json['AppointmentNo'];
// clinicID = json['ClinicID'];
// clinicName = json['ClinicName'] != null ? json['ClinicName'] : "";
// doctorID = json['DoctorID'];
// doctorName = json['DoctorName'];
// orderDate = json['OrderDate'];
// orderNo = json['OrderNo'];
// isAllowCheckIn = json['IsCheckInAllow'];
// procedureIDs = json['ProcedureIds'] != null ? json['ProcedureIds'] : "";
// }
//
// Map<String, dynamic> toJson() {
// final Map<String, dynamic> data = new Map<String, dynamic>();
// data['AppointmentDate'] = this.appointmentDate;
// data['AppointmentNo'] = this.appointmentNo;
// data['ClinicID'] = this.clinicID;
// data['ClinicName'] = this.clinicName;
// data['DoctorID'] = this.doctorID;
// data['DoctorName'] = this.doctorName;
// data['OrderDate'] = this.orderDate;
// data['OrderNo'] = this.orderNo;
// return data;
// }
// }

@ -30,7 +30,6 @@ import 'package:diplomaticquarterapp/widgets/dragable_sheet.dart';
import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class AnicllaryOrdersDetails extends StatefulWidget {
@ -152,8 +151,7 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
width: MediaQuery.of(context).size.width * 0.75,
child: getPaymentMethods(),
),
_amountView(TranslationBase.of(context).patientShareTotalToDo, getTotalValue(), isBold: true, isTotal: true),
// _amountView(TranslationBase.of(context).patientShareTotalToDo, getTotalValue(), isBold: true, isTotal: true),
_amountView(TranslationBase.of(context).patientShareTotalToDo, getTotalValue() + " " + TranslationBase.of(context).sar, isBold: true, isTotal: true),
SizedBox(height: 12),
DefaultButton(
TranslationBase.of(context).payNow.toUpperCase(),
@ -186,7 +184,8 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
: 11,
letterSpacing: -0.5,
color: isBold ? Color(0xff2E303A) : Color(0xff575757),
fontWeight: isTotal ? FontWeight.bold : FontWeight.w600),
fontWeight: isTotal ? FontWeight.bold : FontWeight.w600,
),
);
}
@ -198,15 +197,7 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
child: _getNormalText(title),
),
Expanded(
child: Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
_getNormalText(value, isBold: isBold, isTotal: isTotal),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
child: _getNormalText(value, isBold: isBold, isTotal: isTotal),
),
]),
);
@ -582,9 +573,9 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
});
}),
Utils.tableColumnValue('${value.procedureName}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientShare.toString()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientTaxAmount.toString()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientShareWithTax.toString()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientShare.toString() + " " + TranslationBase.of(context).sar.toUpperCase()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientTaxAmount.toString() + " " + TranslationBase.of(context).sar.toUpperCase()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${value.patientShareWithTax.toString() + " " + TranslationBase.of(context).sar.toUpperCase()}', isLast: true, isCapitable: false, mProjectViewModel: projectViewModel),
]),
);
return tableRow;
@ -680,8 +671,8 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");
@ -829,10 +820,20 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
createAdvancePayment(res, AppoitmentAllHistoryResultList appo) {
DoctorsListService service = new DoctorsListService();
List<dynamic> selectedProcListAPI = [];
selectedProcList.forEach((element) {
selectedProcListAPI.add({
"ApprovalLineItemNo": element.approvalLineItemNo,
"OrderLineItemNo": element.orderLineItemNo,
"ProcedureID": element.procedureID,
});
});
String paymentReference = res['Fort_id'].toString();
service.HIS_createAdvancePayment(appo, widget.projectID.toString(), res['Amount'], res['Fort_id'], res['PaymentMethod'], projectViewModel.user.patientType,
projectViewModel.user.firstName! + " " + projectViewModel.user.lastName!, projectViewModel.user.patientID, localContext,
isAncillaryOrder: true)
isAncillaryOrder: true, orderNo: widget.orderNo, appointmentID: widget.appoNo, selectedProcListAPI: selectedProcListAPI)
.then((res) {
addAdvancedNumberRequest(
Utils.isVidaPlusProject(projectViewModel, widget.projectID)
@ -852,6 +853,7 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
DoctorsListService service = new DoctorsListService();
service.addAdvancedNumberRequest(advanceNumber, paymentReference, appointmentID, localContext).then((res) {
autoGenerateInvoice();
// showAlertDialog("123123123", widget.projectID);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(localContext);
AppToast.showErrorToast(message: err.toString());
@ -886,7 +888,7 @@ class _AnicllaryOrdersState extends State<AnicllaryOrdersDetails> with SingleTic
showAlertDialog(dynamic invoiceNo, dynamic projectID) {
AlertDialogBox(
context: context,
confirmMessage: TranslationBase.of(context).ancillaryOrderPaymentSuccess + invoiceNo.toString(),
confirmMessage: TranslationBase.of(context).ancillaryOrderPaymentSuccess,
okText: TranslationBase.of(context).ok,
okFunction: () {
AlertDialogBox.closeAlertDialog(context);

@ -459,9 +459,8 @@ class _BookConfirmState extends State<BookConfirm> {
payfortProjectDetailsRespModel: payfortProjectDetailsRespModel,
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");

@ -31,7 +31,6 @@ import 'package:diplomaticquarterapp/widgets/new_design/doctor_header.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import '../../config/shared_pref_kay.dart';
@ -42,7 +41,6 @@ class BookSuccess extends StatefulWidget {
DoctorList docObject;
late MyInAppBrowser browser;
// final ChromeSafariBrowser chromeBrowser = new MyChromeSafariBrowser(new MyInAppBrowser());
String appoDateFormatted;
@ -125,8 +123,8 @@ class _BookSuccessState extends State<BookSuccess> {
),
TableRow(
children: [
TableCell(child: _getHeadingText(widget.patientShareResponse.patientShare.toString())),
TableCell(child: _getHeadingText(widget.patientShareResponse.patientShareWithTax.toString())),
TableCell(child: _getHeadingText("SR " + widget.patientShareResponse.patientShare.toString())),
TableCell(child: _getHeadingText("SR " + widget.patientShareResponse.patientShareWithTax.toString())),
],
),
],
@ -714,8 +712,8 @@ class _BookSuccessState extends State<BookSuccess> {
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");
@ -1096,11 +1094,7 @@ class _BookSuccessState extends State<BookSuccess> {
_getHeadingText(text) {
return Container(
padding: EdgeInsets.only(bottom: 10.0, left: 20, right: 20),
child: Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16, color: Colors.white),
mWidth(6),
Text(
child: Text(
text,
textAlign: TextAlign.start,
style: TextStyle(
@ -1110,10 +1104,6 @@ class _BookSuccessState extends State<BookSuccess> {
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16, color: Colors.white) : Container(),
],
),
);
}

@ -40,8 +40,9 @@ class QRCode extends StatefulWidget {
late String? appoQR;
AuthenticatedUser? authUser;
AppSharedPreferences sharedPref = AppSharedPreferences();
bool? isAncillaryOrderCheckIn;
QRCode({required this.patientShareResponse, required this.appoQR, this.appointment});
QRCode({required this.patientShareResponse, required this.appoQR, this.appointment, this.isAncillaryOrderCheckIn});
@override
_QRCodeState createState() => _QRCodeState();
@ -389,6 +390,7 @@ class _QRCodeState extends State<QRCode> {
service.sendCheckinNfcRequest(widget!.patientShareResponse!.appointmentNo!, nfcId, widget.patientShareResponse!.projectID!, checkInBy, widget.patientShareResponse!.clinicID!, context).then((res) {
print(res);
GifLoaderDialogUtils.hideDialog(context);
_showMyDialog(res["SuccessMsg"], this.context);
}).catchError((err) {

@ -9,7 +9,6 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart';
import 'package:flutter/cupertino.dart';
@ -46,18 +45,16 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
AppSharedPreferences sharedPref = new AppSharedPreferences();
var selectedDate = "";
var selectedNextDate = "";
dynamic selectedDateJSON;
dynamic jsonFreeSlots;
final DateFormat dateFormatter = DateFormat('yyyy-MM-dd');
List<TimeSlot> docFreeSlots = [];
List<TimeSlot> dayEvents = [];
List<TimeSlot> nextDayEvents = [];
int selectedButtonIndex = 0;
int selectedNextDayButtonIndex = -1;
dynamic freeSlotsResponse;
// String nextDayAppointmentDate ="";
late ScrollController _scrollController;
var language;
@ -118,11 +115,9 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
final DateFormat formatter = DateFormat('yyyy-MM-dd');
setState(() {
this.selectedDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day, language);
this.selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(day.add(Duration(days: 1)), language);
_calendarController.selectedDate = day;
openTimeSlotsPickerForDate(day, docFreeSlots);
DocAvailableAppointments.selectedDate = formatter.format(day);
selectedNextDayButtonIndex = -1;
_calendarController.selectedDate = day;
print(_calendarController.selectedDate);
});
}
@ -144,10 +139,7 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
child: Text(selectedDate, style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.w600, letterSpacing: -0.64)),
),
DocAvailableAppointments.areSlotsAvailable
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
? Container(
height: 40,
child: ListView.builder(
controller: _scrollController,
@ -160,35 +152,6 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
);
},
),
),
SizedBox(
height: 20,
),
nextDayEvents.isNotEmpty && projectViewModel.havePrivilege(110)
? Container(
padding: EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: Text(
selectedNextDate,
style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w600, letterSpacing: -0.46, color: CustomColors.black),
),
)
: SizedBox(),
Container(
height: 40,
padding: EdgeInsets.only(left: 0, right: 0),
child: ListView.builder(
controller: _scrollController,
scrollDirection: Axis.horizontal,
itemCount: nextDayEvents.length,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.only(right: (index == nextDayEvents.length - 1) ? 16 : 5.0, left: index == 0 ? 16 : 5),
child: index == selectedNextDayButtonIndex ? getSelectedNextDayButton(index) : getNormalNextDayButton(index),
);
},
),
)
],
)
: Center(
child: Padding(
@ -262,7 +225,7 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
Map<String, dynamic> timeSlot = {"isoTime": dayEvents[i].isoTime, "start": dayEvents[i].start.toString(), "end": dayEvents[i].end.toString(), "vidaDate": dayEvents[i].vidaDate};
timeList.add(timeSlot);
}
filterNextDayAppo(freeSlots, timeList.last);
AppSharedPreferences sharedPref = new AppSharedPreferences();
sharedPref.setString('selectedLogSlots', json.encode(timeList));
DocAvailableAppointments.selectedTime = dayEvents[selectedButtonIndex].isoTime;
@ -271,27 +234,12 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
});
}
filterNextDayAppo(List<TimeSlot> freeSlots, Map<String, dynamic> listList) {
DateTime dateStart = DateTime.parse(listList['end']).add(Duration(days: 1));
DateTime dateStartObj = new DateTime(dateStart.year, dateStart.month, dateStart.day, 0, 0, 0, 0, 0);
nextDayEvents = [];
DateTime beforeHour = new DateTime(dateStart.year, dateStart.month, dateStart.day, 6, 0, 0, 0, 0);
if (projectViewModel.havePrivilege(110)) {
freeSlots.forEach((v) {
if (v.start == dateStartObj && v.end!.isBefore(beforeHour)) nextDayEvents.add(v);
});
} else {
nextDayEvents = [];
}
// print(nextDayEvents);
}
Future<Map<DateTime, List>> _getJSONSlots() async {
Map<DateTime, List> _eventsParsed;
List<FreeSlot> slotsList = [];
DateTime date;
final DateFormat formatter = DateFormat('HH:mm');
final DateFormat dateFormatter = DateFormat('yyyy-MM-dd');
for (var i = 0; i < freeSlotsResponse.length; i++) {
date = (isLiveCareSchedule != null && isLiveCareSchedule)
? DateUtil.convertStringToDate(freeSlotsResponse[i])
@ -311,7 +259,6 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
),
),
);
DocAvailableAppointments.selectedAppoDateTime = (isLiveCareSchedule != null && isLiveCareSchedule)
? DateUtil.convertStringToDate(freeSlotsResponse[0])
: DateUtil.convertStringToDateSaudiTimezone(
@ -330,16 +277,6 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
),
),
language);
selectedNextDate = DateUtil.getWeekDayMonthDayYearDateFormatted(
(isLiveCareSchedule != null && isLiveCareSchedule)
? DateUtil.convertStringToDate(freeSlotsResponse[0]).add(Duration(days: 1))
: DateUtil.convertStringToDateSaudiTimezone(
freeSlotsResponse[0],
int.parse(
widget.doctor.projectID.toString(),
),
).add(Duration(days: 1)),
language);
selectedDateJSON = freeSlotsResponse[0];
});
openTimeSlotsPickerForDate(
@ -383,10 +320,8 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
setState(() {
selectedButtonIndex = index;
selectedNextDayButtonIndex = -1;
DocAvailableAppointments.selectedTime = dayEvents[index].isoTime;
print(DocAvailableAppointments.selectedTime);
DocAvailableAppointments.selectedDate = dateFormatter.format(_calendarController.selectedDate!);
});
projectViewModel.analytics.appointment.book_appointment_time_selection(appointment_type: 'regular', dateTime: timeslot.end, doctor: widget.doctor);
},
@ -407,7 +342,6 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
setState(() {
selectedButtonIndex = index;
DocAvailableAppointments.selectedTime = dayEvents[index].isoTime;
DocAvailableAppointments.selectedDate = dateFormatter.format(_calendarController.selectedDate!);
print(DocAvailableAppointments.selectedTime);
});
},
@ -415,54 +349,6 @@ class _DocAvailableAppointmentsState extends State<DocAvailableAppointments> wit
);
}
Widget getNormalNextDayButton(int index) {
return CustomTextButton(
backgroundColor: Colors.white,
elevation: 0,
side: BorderSide(
color: Colors.black, //Color of the border
style: BorderStyle.solid, //Style of the border
width: 1.5 //width of the border
),
onPressed: () {
final timeslot = nextDayEvents[index];
DocAvailableAppointments.selectedAppoDateTime = timeslot.end;
setState(() {
selectedButtonIndex = -1;
selectedNextDayButtonIndex = index;
DocAvailableAppointments.selectedTime = nextDayEvents[index].isoTime;
DocAvailableAppointments.selectedDate = dateFormatter.format(_calendarController.selectedDate!.add(Duration(days: 1)));
print(DocAvailableAppointments.selectedTime);
});
projectViewModel.analytics.appointment.book_appointment_time_selection(appointment_type: 'regular', dateTime: timeslot.end, doctor: widget.doctor);
},
child: Text(nextDayEvents[index].isoTime!, style: TextStyle(fontSize: 12.0, color: Color(0xFF60686b))),
);
}
Widget getSelectedNextDayButton(int index) {
return CustomTextButton(
backgroundColor: nextDayEvents[index].isoTime == TranslationBase.of(context).waitingAppointment ? CustomColors.darkOrange : CustomColors.green,
elevation: 0,
side: BorderSide(
color: nextDayEvents[index].isoTime == TranslationBase.of(context).waitingAppointment ? CustomColors.darkOrange : CustomColors.green, //Color of the border
style: BorderStyle.solid, //Style of the border
width: 1.5 //width of the border
),
onPressed: () {
setState(() {
selectedButtonIndex = -1;
selectedNextDayButtonIndex = index;
DocAvailableAppointments.selectedTime = nextDayEvents[index].isoTime;
DocAvailableAppointments.selectedDate = dateFormatter.format(_calendarController.selectedDate!.add(Duration(days: 1)));
print(DocAvailableAppointments.selectedTime);
});
},
child: Text(nextDayEvents[index].isoTime!, style: TextStyle(fontSize: 12.0, color: Colors.white)),
);
}
getDoctorFreeSlots(context, DoctorList docObject) {
print(DocAvailableAppointments.initialSlotDuration);
GifLoaderDialogUtils.showMyDialog(context);

@ -70,7 +70,7 @@ class _SearchByClinicState extends State<SearchByClinic> {
@override
void initState() {
locationUtils = new LocationUtils(isShowConfirmDialog: true, isShowLocationTimeoutDialog: false, context: context);
locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context);
WidgetsBinding.instance.addPostFrameCallback((_) => getClinicsList());
checkPVM();
super.initState();

@ -14,8 +14,6 @@ import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart' as list;
import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_info_response_model.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_request_info_response_model.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart';
import 'package:diplomaticquarterapp/routes.dart';
@ -469,42 +467,6 @@ class _MyFamily extends State<MyFamily> with TickerProviderStateMixin {
});
}
checkIfIsInPatient(BuildContext context) {
bool isAdmitted = false;
bool hasAdmissionRequest = false;
GetAdmissionInfoResponseModel getAdmissionInfoResponseModel;
GetAdmissionRequestInfoResponseModel getAdmissionRequestInfoResponseModel;
ClinicListService service = new ClinicListService();
service.checkIfInPatientAPI(context).then((res) {
if (res['MessageStatus'] == 1) {
isAdmitted = res['isAdmitted'];
hasAdmissionRequest = res['hasAdmissionRequests'];
print("IS ADMITTED: $isAdmitted");
print("Has Admission Request: $hasAdmissionRequest");
if (isAdmitted) {
if (res['PatientAdmittedInformation'].length != 0) {
getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]);
projectViewModel.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']);
projectViewModel.setInPatientAdmissionInfo(getAdmissionInfoResponseModel);
projectViewModel.setIsPatientAdmitted(true);
}
}
if (hasAdmissionRequest) {
if (res['MedicalInstruction'].length != 0) {
getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]);
// projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['ProjectID']);
projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']);
projectViewModel.setInPatientAdmissionRequest(getAdmissionRequestInfoResponseModel);
projectViewModel.setPatientHasAdmissionRequest(true);
}
}
} else {}
}).catchError((err) {
projectViewModel.setIsPatientAdmitted(false);
projectViewModel.setPatientHasAdmissionRequest(false);
});
}
loginAfter(result, context) async {
var currentLang = await sharedPref.getString(APP_LANGUAGE);
Provider.of<ProjectViewModel>(AppGlobal.context, listen: false).setPrivilege(privilegeList: result, isLoginChild: true);
@ -539,7 +501,6 @@ class _MyFamily extends State<MyFamily> with TickerProviderStateMixin {
try {
// await appointmentRateViewModel.getIsLastAppointmentRatedList();
checkIfIsInPatient(context);
await getToDoCount();
if (appointmentRateViewModel.isHaveAppointmentNotRate) {
Navigator.pushAndRemoveUntil(

@ -8,7 +8,6 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class BillAmount extends StatefulWidget {
final Function changeCurrentTab;
@ -99,13 +98,7 @@ class _BillAmountState extends State<BillAmount> {
child: _getNormalText(TranslationBase.of(context).patientShareTotalToDo),
),
Expanded(
child: Row(
children: [
SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
_getNormalText(TranslationBase.of(context).sar + ' ${widget.patientER_RC.patientERTransportationMethod!.priceTotal}', isBold: true, isTotal: true),
],
),
child: _getNormalText(TranslationBase.of(context).sar + ' ${widget.patientER_RC.patientERTransportationMethod!.priceTotal}', isBold: true, isTotal: true),
)
],
),

@ -22,7 +22,6 @@ import 'package:diplomaticquarterapp/widgets/pickupLocation/PickupLocationFromMa
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import '../AvailableAppointmentsPage.dart';
@ -50,7 +49,6 @@ class _PickupLocationState extends State<PickupLocation> {
AppoitmentAllHistoryResultList? myAppointment;
HospitalsModel? _selectedHospital;
LocationDetails? _result ;
LocationUtils? locationUtils;
late ProjectViewModel projectViewModel;
@ -521,20 +519,10 @@ class _PickupLocationState extends State<PickupLocation> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(TranslationBase.of(context).patientShareTotalToDo, style: TextStyle(fontSize: 13.0, letterSpacing: -0.64, fontWeight: FontWeight.w600)),
Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
(widget.patientER_RC.transportationDetails!.tripType == 1
? ' ${widget.patientER_RC.patientERTransportationMethod!.priceTotal}'
: ' ${(widget.patientER_RC.patientERTransportationMethod!.priceTotal * 2)}'),
TranslationBase.of(context).sar + (widget.patientER_RC.transportationDetails!.tripType == 1 ? ' ${widget.patientER_RC.patientERTransportationMethod!.priceTotal}' : ' ${(widget.patientER_RC.patientERTransportationMethod!.priceTotal * 2)}'),
style: TextStyle(fontSize: 16.0, letterSpacing: -0.64, fontWeight: FontWeight.bold),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
],
)
],

@ -11,7 +11,6 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
enum Direction { ToHospital, FromHospital }
@ -124,22 +123,14 @@ class _SelectTransportationMethodState extends State<SelectTransportationMethod>
),
Expanded(
flex: 1,
child: Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
' ${widget.amRequestViewModel.amRequestModeList[index].priceTotal}',
child: Text(
TranslationBase.of(context).sar + ' ${widget.amRequestViewModel.amRequestModeList[index].priceTotal}',
style: TextStyle(
fontSize: 12.0,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
)
],
),
@ -334,18 +325,10 @@ class _SelectTransportationMethodState extends State<SelectTransportationMethod>
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(TranslationBase.of(context).patientShareTotalToDo, style: TextStyle(fontSize: 13.0, letterSpacing: -0.64, fontWeight: FontWeight.w600)),
Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
(_way == Way.OneWay ? ' ${_erTransportationMethod.priceTotal}' : ' ${(_erTransportationMethod.priceTotal * 2)}'),
TranslationBase.of(context).sar + (_way == Way.OneWay ? ' ${_erTransportationMethod.priceTotal}' : ' ${(_erTransportationMethod.priceTotal * 2)}'),
style: TextStyle(fontSize: 16.0, letterSpacing: -0.64, fontWeight: FontWeight.bold),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
],
)
],

@ -9,7 +9,6 @@ import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
@ -19,7 +18,6 @@ class Summary extends StatefulWidget {
final PatientER_RC patientER_RC;
final AmRequestViewModel amRequestViewModel;
final TabController tabController;
Summary({Key? key, required this.changeCurrentTab, required this.patientER, required this.patientER_RC, required this.amRequestViewModel, required this.tabController});
@override
@ -27,6 +25,7 @@ class Summary extends StatefulWidget {
}
class _SummaryState extends State<Summary> {
@override
Widget build(BuildContext context) {
ProjectViewModel projectViewModel = Provider.of(context);
@ -130,20 +129,13 @@ class _SummaryState extends State<Summary> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(TranslationBase.of(context).patientShareTotalToDo, style: TextStyle(fontSize: 13.0, letterSpacing: -0.64, fontWeight: FontWeight.w600)),
Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
TranslationBase.of(context).sar +
(widget.patientER_RC.transportationDetails!.tripType == 1
? ' ${widget.patientER_RC.patientERTransportationMethod!.priceTotal}'
: ' ${(widget.patientER_RC.patientERTransportationMethod!.priceTotal * 2)}'),
style: TextStyle(fontSize: 16.0, letterSpacing: -0.64, fontWeight: FontWeight.bold),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
],
)
],

@ -27,7 +27,6 @@ import 'package:diplomaticquarterapp/widgets/dragable_sheet.dart';
import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class EROnlineCheckInPaymentDetails extends StatefulWidget {
@ -279,7 +278,8 @@ class _EROnlineCheckInPaymentDetailsState extends State<EROnlineCheckInPaymentDe
width: MediaQuery.of(context).size.width * 0.75,
child: getPaymentMethods(),
),
_amountView(TranslationBase.of(context).patientShareTotalToDo, erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax.toString(), isBold: true, isTotal: true),
_amountView(TranslationBase.of(context).patientShareTotalToDo, erOnlineCheckInPaymentDetailsResponse!.patientShareWithTax.toString() + " " + TranslationBase.of(context).sar,
isBold: true, isTotal: true),
SizedBox(height: 12),
DefaultButton(
TranslationBase.of(context).payNow.toUpperCase(),
@ -423,9 +423,8 @@ class _EROnlineCheckInPaymentDetailsState extends State<EROnlineCheckInPaymentDe
payfortProjectDetailsRespModel: payfortProjectDetailsRespModel,
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");
@ -598,15 +597,7 @@ class _EROnlineCheckInPaymentDetailsState extends State<EROnlineCheckInPaymentDe
child: _getNormalText(title),
),
Expanded(
child: Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
_getNormalText(value, isBold: isBold, isTotal: isTotal),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
child: _getNormalText(value, isBold: isBold, isTotal: isTotal),
),
]),
);

@ -13,12 +13,10 @@ import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
@ -93,18 +91,10 @@ class RRTPlaceOrderPage extends StatelessWidget {
SizedBox(
height: 5,
),
Row(
children: [
projectViewModel!.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 18, height: 18),
mWidth(6),
Text(
"${selectedProcedure.patientShareWithTax ?? '- - -'}",
"${selectedProcedure.patientShareWithTax ?? '- - -'} ${localize.sar}",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
),
mWidth(6),
projectViewModel!.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 18, height: 18) : Container(),
],
),
],
),
),
@ -223,6 +213,8 @@ class RRTPlaceOrderPage extends StatelessWidget {
Navigator.pop(_context);
Navigator.pop(_context);
gotoRRTRoot();
},
);
}

@ -1,5 +1,4 @@
import 'package:diplomaticquarterapp/core/model/AlHabibMedicalService/ComprehensiveMedicalCheckup/GetCMCAllOrdersResponseModel.dart';
import 'package:diplomaticquarterapp/core/service/AlHabibMedicalService/customer_addresses_service.dart';
import 'package:diplomaticquarterapp/core/viewModels/er/rrt-view-model.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/rrt/RRTProcedureList.dart';
@ -13,13 +12,11 @@ import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class RRTRequestPage extends StatefulWidget {
@ -206,22 +203,14 @@ class RRTRequestPageState extends State<RRTRequestPage> {
),
),
Expanded(
child: Row(
children: [
projectViewModel!.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
amount,
child: Text(
'$amount ${TranslationBase.of(context).sar}',
style: TextStyle(
fontSize: 12,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel!.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
),
],
),
@ -242,22 +231,14 @@ class RRTRequestPageState extends State<RRTRequestPage> {
),
),
Expanded(
child: Row(
children: [
projectViewModel!.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
vat,
child: Text(
'$vat ${TranslationBase.of(context).sar}',
style: TextStyle(
fontSize: 12,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel!.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
),
],
),
@ -278,17 +259,13 @@ class RRTRequestPageState extends State<RRTRequestPage> {
),
),
Expanded(
child: Row(
children: [
projectViewModel!.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 14, height: 14),
mWidth(6),
Text(
total,
style: TextStyle(fontSize: 14, letterSpacing: -0.48, fontWeight: FontWeight.bold, color: CustomColors.black),
child: Text(
'$total ${TranslationBase.of(context).sar}',
style: TextStyle(
fontSize: 14,
letterSpacing: -0.48,
fontWeight: FontWeight.bold,
),
mWidth(6),
projectViewModel!.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
),
],

@ -11,7 +11,6 @@ import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
@ -167,12 +166,8 @@ class _InPatientPendingAdvancePaymentState extends State<InPatientPendingAdvance
letterSpacing: -0.64,
),
),
Row(
children: [
SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
"${widget.inPatientAdvanceResponseModel.responseInpatientAdvanceInfo![0].requestedAmount}",
TranslationBase.of(context).sar + " ${widget.inPatientAdvanceResponseModel.responseInpatientAdvanceInfo![0].requestedAmount}",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
@ -181,8 +176,6 @@ class _InPatientPendingAdvancePaymentState extends State<InPatientPendingAdvance
),
],
),
],
),
SizedBox(height: 12),
Text(
TranslationBase.of(context).YouCanPayByTheFollowingOptions,
@ -262,7 +255,6 @@ class _InPatientPendingAdvancePaymentState extends State<InPatientPendingAdvance
int clinicID = projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.clinicID! : 17;
service
.getInPatientPaymentLink(
widget.inPatientAdvanceResponseModel.responseInpatientAdvanceInfo![0].paymentRequestID!,
projectViewModel.inPatientProjectID,
// projectViewModel.getAdmissionInfoResponseModel.admissionNo!,
projectViewModel.isPatientAdmitted ? projectViewModel.getAdmissionInfoResponseModel.admissionRequestNo! : projectViewModel.getAdmissionRequestInfoResponseModel.admissionRequestNo!,

@ -514,8 +514,7 @@ class InPatientGeneralConsent extends StatelessWidget {
.then((res) {
GifLoaderDialogUtils.hideDialog(context);
if (res["MessageStatus"] == 1) {
AppToast.showSuccessToast(message: res["SuccessMsg"] ?? TranslationBase.of(context).success);
Navigator.of(context);
AppToast.showErrorToast(message: res["SuccessMsg"]);
} else {
AppToast.showErrorToast(message: res["endUserMessage"]);
}

@ -105,7 +105,7 @@ class _AppointmentDetailsState extends State<AppointmentDetails> with SingleTick
widget.appo.doctorImageURL!,
widget.appo.doctorSpeciality!,
"",
widget.appo.projectName ?? "",
widget.appo.projectName!,
DateUtil.convertStringToDate(widget.appo.appointmentDate!),
widget.appo.isLiveCareAppointment! ? DateUtil.convertStringToDate(widget.appo.appointmentDate!).toString().split(" ")[1].substring(0, 5) : widget.appo.startTime!.substring(0, 5),
"",

@ -409,7 +409,6 @@ class _AppointmentActionsState extends State<AppointmentActions> {
if (res['ListLabResultsByAppNo'] != null) {
patientLabOrders.orderNo = res['ListLabResultsByAppNo'][0]['OrderNo'].toString();
patientLabOrders.invoiceNo = res['ListLabResultsByAppNo'][0]['InvoiceNo'].toString();
patientLabOrders.invoiceType = res['ListLabResultsByAppNo'][0]['InvoiceType'].toString();
patientLabOrders.clinicID = widget.appo.clinicID;
patientLabOrders.clinicDescription = widget.appo.clinicName;
patientLabOrders.projectID = widget.appo.projectID.toString();

@ -1,10 +1,12 @@
import 'dart:developer';
import 'dart:io';
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:diplomaticquarterapp/analytics/google-analytics.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
import 'package:diplomaticquarterapp/core/enum/PayfortEnums.dart';
import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart';
import 'package:diplomaticquarterapp/core/model/privilege/ProjectDetailListModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/Appointments/AppoimentAllHistoryResultList.dart';
import 'package:diplomaticquarterapp/models/Appointments/DoctorListResponse.dart';
@ -34,15 +36,19 @@ import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/location_util.dart';
import 'package:diplomaticquarterapp/uitl/penguin_method_channel.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart';
import 'package:diplomaticquarterapp/widgets/bottom_options/bottom_sheet.dart';
import 'package:diplomaticquarterapp/widgets/data_display/medical/doctor_card.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/alert_dialog.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:diplomaticquarterapp/widgets/my_rich_text.dart';
import 'package:diplomaticquarterapp/widgets/nfc/nfc_reader_sheet.dart';
import 'package:diplomaticquarterapp/widgets/others/app_expandable_notifier.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
@ -50,6 +56,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/countdown_timer_controller.dart';
import 'package:flutter_countdown_timer/current_remaining_time.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:permission_handler/permission_handler.dart';
@ -97,6 +104,9 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
List<AncillaryOrdersListModel> ancillaryLists = [];
List<OBGyneProcedureListResponse> obGyneAppoList = [];
String? transID;
bool _supportsNFC = false;
late LocationUtils locationUtils;
ProjectDetailListModel projectDetailListModel = ProjectDetailListModel();
@override
void initState() {
@ -124,6 +134,9 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
Widget build(BuildContext context) {
toDoProvider = Provider.of<ToDoCountProviderModel>(context);
projectViewModel = Provider.of(context);
FlutterNfcKit.nfcAvailability.then((value) {
_supportsNFC = (value == NFCAvailability.available);
});
return AppScaffold(
appBarTitle: TranslationBase.of(context).todoList,
imagesInfo: imagesInfo,
@ -441,6 +454,24 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
isLiveCareAppointment: false,
date: DateUtil.convertStringToDate(ancillaryLists[0].ancillaryOrderList![index].orderDate),
isSortByClinic: true,
isAllowCheckInAncillary: ancillaryLists[0].ancillaryOrderList![index].isCheckInAllow!,
// isAllowCheckInAncillary: true,
onAncillaryCheckInTap: () {
AppoitmentAllHistoryResultList appo = new AppoitmentAllHistoryResultList();
appo.doctorTitle = TranslationBase.of(context).dr.toString();
appo.doctorNameObj = ancillaryLists[0].ancillaryOrderList![index].doctorName;
appo.doctorID = ancillaryLists[0].ancillaryOrderList![index].doctorID;
appo.doctorImageURL = "https://hmgwebservices.com/Images/MobileImages/DUBAI/unkown.png";
appo.doctorSpeciality = [""];
appo.projectName = ancillaryLists[0].projectName;
appo.appointmentDate = ancillaryLists[0].ancillaryOrderList![index].orderDate;
appo.isLiveCareAppointment = true;
appo.doctorRate = 5;
appo.actualDoctorRate = 0;
appo.noOfPatientsRate = 0;
ShowAncillaryOrderOnlineCheckInBottomSheet(ancillaryLists[0].ancillaryOrderList![index], ancillaryLists[0].projectID!);
},
);
},
itemCount: ancillaryLists[0].ancillaryOrderList!.length,
@ -1164,12 +1195,88 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
});
}
ShowAncillaryOrderOnlineCheckInBottomSheet(AncillaryOrderList ancillaryOrderList, int projectID) {
showMyBottomSheet(context,
callBackFunc: () {},
child: Padding(
padding: const EdgeInsets.all(21.0),
child: Column(
children: [
Text(TranslationBase.of(context).scanQRHospital,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
letterSpacing: -0.48,
)),
mHeight(21),
GridView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 12),
children: [
attendanceMethod(TranslationBase.of(context).scanNFC, "assets/images/nfc/contactless.svg", true, () {
if (_supportsNFC) {
Future.delayed(const Duration(milliseconds: 500), () {
showNfcReader(context, onNcfScan: (String nfcId) {
Future.delayed(const Duration(milliseconds: 100), () {
print(nfcId);
generateQueueNumber(ancillaryOrderList, projectID);
// getProjectIDFromNFC(nfcId, true);
// Navigator.push(context, FadePage(page: EROnlineCheckInPaymentDetails()));
});
}, onCancel: () {
Navigator.of(context).pop();
});
});
} else {
//NFCNotSupported
AppToast.showErrorToast(message: TranslationBase.of(context).NFCNotSupported);
}
}),
attendanceMethod(TranslationBase.of(context).pharmaLiveCareScanQR, "assets/images/new/services/qr_code.svg", true, () async {
String onlineCheckInQRCode = (await BarcodeScanner.scan().then((value) => value.rawContent));
if (onlineCheckInQRCode != "") {
print(onlineCheckInQRCode);
generateQueueNumber(ancillaryOrderList, projectID);
// getProjectIDFromNFC(onlineCheckInQRCode, true);
// sendNfcCheckInRequest(onlineCheckInQRCode, 2);
} else {}
}),
attendanceMethod(TranslationBase.of(context).checkInViaLocation, "assets/images/new/services/location.svg", true, () {
startLocationCheckIn(ancillaryOrderList, projectID);
})
],
),
],
),
));
}
Future navigateToQR(context, String appoQR, PatientShareResponse patientShareResponse, AppoitmentAllHistoryResultList appintment) async {
Navigator.push(context, FadePage(page: QRCode(patientShareResponse: patientShareResponse, appoQR: appoQR, appointment: appintment))).then((value) {
getPatientAppointmentHistory();
});
}
startLocationCheckIn(AncillaryOrderList ancillaryOrderList, int projectID) async {
GifLoaderDialogUtils.showMyDialog(context);
locationUtils = new LocationUtils(isShowConfirmDialog: true, context: context);
locationUtils.getCurrentLocation(callBack: (value) {
projectDetailListModel = Utils.getProjectDetailObj(projectViewModel, widget.appointment!.projectID);
double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000;
print(dist);
if (dist <= projectDetailListModel.geofenceRadius!) {
GifLoaderDialogUtils.hideDialog(context);
generateQueueNumber(ancillaryOrderList, projectID);
// sendNfcCheckInRequest(projectDetailListModel.checkInQrCode!, 2);
} else {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: TranslationBase.of(context).locationCheckInError);
}
});
}
openPaymentDialog(AppoitmentAllHistoryResultList appo, PatientShareResponse patientShareResponse) {
showGeneralDialog(
barrierColor: Colors.black.withOpacity(0.5),
@ -1531,8 +1638,8 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");
@ -1575,6 +1682,59 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
});
}
generateQueueNumber(AncillaryOrderList ancillaryOrderList, int projectID) {
GifLoaderDialogUtils.showMyDialog(context);
DoctorsListService service = new DoctorsListService();
service
.getLabQueueNumber(projectID, projectViewModel.authenticatedUserObject.user.patientID!, Utils.isVidaPlusProject(projectViewModel, projectID), ancillaryOrderList.invoiceNo.toString(),
ancillaryOrderList.orderNo.toString())
.then((res) {
GifLoaderDialogUtils.hideDialog(context);
showAlertDialog(res['QLineResponse']['patientCallNo']);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
AppToast.showErrorToast(message: err);
print(err);
});
}
// autoGenerateInvoice(AncillaryOrderList ancillaryOrderList, int projectID) {
// List<dynamic> selectedProcListAPI = [];
//
// ancillaryOrderList.ancillaryProcedureListModels!.forEach((element) {
// selectedProcListAPI.add({
// "ApprovalLineItemNo": element.approvalLineItemNo,
// "OrderLineItemNo": element.orderLineItemNo,
// "ProcedureID": element.procedureID,
// });
// });
//
// GifLoaderDialogUtils.showMyDialog(context);
//
// DoctorsListService service = new DoctorsListService();
// service.autoGenerateAncillaryOrdersInvoice(ancillaryOrderList.orderNo, projectID, ancillaryOrderList.appointmentNo, selectedProcListAPI, projectViewModel.isArabic ? 1 : 2, context).then((res) {
// GifLoaderDialogUtils.hideDialog(context);
// showAlertDialog(res['AncillaryOrderInvoiceList'][0]['PatientCallNo']);
// }).catchError((err) {
// GifLoaderDialogUtils.hideDialog(context);
// AppToast.showErrorToast(message: err);
// print(err);
// });
// }
showAlertDialog(dynamic queueNo) {
AlertDialogBox(
context: context,
confirmMessage: TranslationBase.of(context).ancillaryOrderCheckInSuccess + queueNo.toString(),
okText: TranslationBase.of(context).ok,
okFunction: () {
AlertDialogBox.closeAlertDialog(context);
Navigator.of(context).pop();
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (context) => LandingPage()), (Route<dynamic> r) => false);
}).showAlertDialog(context);
}
insertLiveCareVIDARequest(AppoitmentAllHistoryResultList appo) {
GifLoaderDialogUtils.showMyDialog(context);
DoctorsListService service = new DoctorsListService();
@ -1595,6 +1755,29 @@ class _ToDoState extends State<ToDo> with SingleTickerProviderStateMixin {
});
}
Widget attendanceMethod(String title, String image, bool isEnabled, VoidCallback onPress) => InkWell(
onTap: () {
Navigator.pop(context);
onPress();
},
child: Container(
decoration: containerColorRadiusBorderWidth(Colors.white, 15, CustomColors.darkGreyColor, 1),
clipBehavior: Clip.antiAlias,
padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: SvgPicture.asset(image, color: Colors.black, alignment: Alignment.topLeft)),
Text(
title,
style: TextStyle(color: Colors.black, fontSize: 14, letterSpacing: -0.68, fontWeight: FontWeight.bold),
),
// title.toText17(isBold: true, color: Colors.white),
],
),
),
);
ancillaryOrdersDetails(item, projectId) {
Navigator.push(
context,

@ -171,17 +171,17 @@ class _InsuranceCardState extends State<InsuranceCard> {
SizedBox(
height: 8.5,
),
// if (model.insurance[index].isActive == true)
// Container(
// color: Colors.transparent,
// child: DefaultButton(
// TranslationBase.of(context).seeDetails,
// () => {
// getDetails(model.insurance[index]),
// },
// ),
// width: double.infinity,
// ),
if (model.insurance[index].isActive == true)
Container(
color: Colors.transparent,
child: DefaultButton(
TranslationBase.of(context).seeDetails,
() => {
getDetails(model.insurance[index]),
},
),
width: double.infinity,
),
],
),
),

@ -41,7 +41,6 @@ import 'package:diplomaticquarterapp/uitl/penguin_method_channel.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/vital_signs/vital_sign.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/covid_consent_dialog.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/location_selection_dialog.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/radio_selection_dialog.dart';
@ -230,9 +229,6 @@ class ServicesView extends StatelessWidget {
} else if (hmgServices.action == 1) {
openLiveCare(context);
} else if (hmgServices.action == 2) {
//todo for temporary basis
// Navigator.push(context, FadePage(page: VitalSigns()));
// initPenguinSDK();
if (projectViewModel.isIndoorNavigationEnabled) {
if (!isLocked) openNavigationProjectSelection(context);

@ -133,24 +133,7 @@ class _LiveCarePatmentPageState extends State<LiveCarePatmentPage> {
),
),
Expanded(
child: (widget.getERAppointmentFeesList.currency! == "ريال" || widget.getERAppointmentFeesList.currency! == "SAR")
? Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
widget.getERAppointmentFeesList.amount!,
style: TextStyle(
fontSize: 12,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
)
: Text(
child: Text(
widget.getERAppointmentFeesList.amount! + " " + widget.getERAppointmentFeesList.currency!,
style: TextStyle(
fontSize: 12,
@ -178,24 +161,7 @@ class _LiveCarePatmentPageState extends State<LiveCarePatmentPage> {
),
),
Expanded(
child: (widget.getERAppointmentFeesList.currency! == "ريال" || widget.getERAppointmentFeesList.currency! == "SAR")
? Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
widget.getERAppointmentFeesList.tax!,
style: TextStyle(
fontSize: 12,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
)
: Text(
child: Text(
widget.getERAppointmentFeesList.tax! + " " + widget.getERAppointmentFeesList.currency!,
style: TextStyle(
fontSize: 12,
@ -223,24 +189,7 @@ class _LiveCarePatmentPageState extends State<LiveCarePatmentPage> {
),
),
Expanded(
child: (widget.getERAppointmentFeesList.currency! == "ريال" || widget.getERAppointmentFeesList.currency! == "SAR")
? Row(
children: [
projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
widget.getERAppointmentFeesList.total!,
style: TextStyle(
fontSize: 12,
letterSpacing: -0.48,
fontWeight: FontWeight.w600,
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
)
: Text(
child: Text(
widget.getERAppointmentFeesList.total! + " " + widget.getERAppointmentFeesList.currency!,
style: TextStyle(
fontSize: 12,

@ -486,9 +486,9 @@ class _clinic_listState extends State<ClinicList> {
payfortProjectDetailsRespModel: payfortProjectDetailsRespModel,
currency: projectViewModel.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
GifLoaderDialogUtils.hideDialog(localContext!);
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
GifLoaderDialogUtils.hideDialog(localContext!);

@ -346,16 +346,10 @@ class _ConfirmLogin extends State<ConfirmLogin> {
}
loginWithSMS(type) async {
if (type == 4) {
var channel = WhatsappMethodChannel();
// var whatsappStatus = await channel.isWhatsAppInstalled();
// if(whatsappStatus) {
// print("whatapp is installed");
channel.handleHandShake();
// }else{
// print("whatapp is not installed");
// if (type == 4) {
// var channel = WhatsappMethodChannel();
// await channel.handleHandShake();
// }
}
//if (!el.disabled) {
if (this.user != null && this.registerd_data == null) {
@ -709,41 +703,37 @@ class _ConfirmLogin extends State<ConfirmLogin> {
}
checkIfUserAgreedBefore(CheckActivationCode result) {
if (projectViewModel.havePrivilege(109)) {
this.authService.checkIfUserAgreed().then((result) {
if (result['IsPatientAlreadyAgreed']) {
goToHome();
} else {
this.authService.getUserAgreementContent().then((result) {
GifLoaderDialogUtils.hideDialog(AppGlobal.context);
Navigator.pushAndRemoveUntil(
context,
FadePage(
page: UserLoginAgreementPage(
userAgreementText: result['UserAgreementContent'],
authenticatedUserObject: authenticatedUserObject,
appointmentRateViewModel: appointmentRateViewModel,
selectedOption: selectedOption,
),
),
(r) => false);
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
print(err);
});
}
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
print(err);
});
} else {
goToHome();
}
// this.authService.checkIfUserAgreed().then((result) {
// if (result['IsPatientAlreadyAgreed']) {
// goToHome();
// } else {
// this.authService.getUserAgreementContent().then((result) {
// GifLoaderDialogUtils.hideDialog(AppGlobal.context);
// Navigator.pushAndRemoveUntil(
// context,
// FadePage(
// page: UserLoginAgreementPage(
// userAgreementText: result['UserAgreementContent'],
// authenticatedUserObject: authenticatedUserObject,
// appointmentRateViewModel: appointmentRateViewModel,
// selectedOption: selectedOption,
// ),
// ),
// (r) => false);
// }).catchError((err) {
// GifLoaderDialogUtils.hideDialog(context);
// print(err);
// });
// }
// }).catchError((err) {
// GifLoaderDialogUtils.hideDialog(context);
// print(err);
// });
// if (result.isNeedUserAgreement == true) {
// // move to agreement page.
//move to agreement page.
// } else {
// goToHome();
goToHome();
// }
}

@ -362,12 +362,12 @@ class _Login extends State<Login> {
projectViewModel.setPrivilege(privilegeList: result);
result = CheckActivationCode.fromJson(result);
result.list.isFamily = false;
await this.sharedPref.setString(BLOOD_TYPE,
this.sharedPref.setString(BLOOD_TYPE,
result.patientBloodType != null ? result.patientBloodType : "");
await this.sharedPref.setObject(USER_PROFILE, result.list);
await this.sharedPref.setObject(MAIN_USER, result.list);
await this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID);
await this.sharedPref.setString(TOKEN, result.authenticationTokenID);
this.sharedPref.setObject(USER_PROFILE, result.list);
this.sharedPref.setObject(MAIN_USER, result.list);
this.sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID);
this.sharedPref.setString(TOKEN, result.authenticationTokenID);
await authenticatedUserObject.getUser(getUser: true);
authenticatedUserObject.isLogin = true;
appointmentRateViewModel.isLogin = true;

@ -3,8 +3,6 @@ import 'package:diplomaticquarterapp/core/viewModels/TermsConditionsViewModel.da
import 'package:diplomaticquarterapp/core/viewModels/appointment_rate_view_model.dart';
import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/models/Appointments/toDoCountProviderModel.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_info_response_model.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_request_info_response_model.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/rateAppointment/rate_appointment_doctor.dart';
@ -15,7 +13,6 @@ import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/Loader/gif_loader_container.dart';
import 'package:diplomaticquarterapp/widgets/buttons/custom_text_button.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
@ -54,7 +51,6 @@ class _UserLoginAgreementPageState extends State<UserLoginAgreementPage> {
NavigationDelegate(
onProgress: (int progress) {
// Update loading bar.
print("Progress: $progress");
},
onPageStarted: (String url) {},
onPageFinished: (String url) {
@ -86,15 +82,7 @@ class _UserLoginAgreementPageState extends State<UserLoginAgreementPage> {
showNewAppBar: true,
isShowDecPage: false,
appBarTitle: TranslationBase.of(context).userAgreement,
body: isPageLoaded
? WebViewWidget(controller: _controller)
: Container(
child: Center(
child: GifLoaderContainer(
barrierDismissible: false,
),
),
),
body: WebViewWidget(controller: _controller),
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: SingleChildScrollView(child: WebViewWidget(controller: _controller)
@ -205,39 +193,6 @@ class _UserLoginAgreementPageState extends State<UserLoginAgreementPage> {
});
}
checkIfIsInPatient() {
bool isAdmitted = false;
bool hasAdmissionRequest = false;
GetAdmissionInfoResponseModel getAdmissionInfoResponseModel;
GetAdmissionRequestInfoResponseModel getAdmissionRequestInfoResponseModel;
ClinicListService service = new ClinicListService();
service.checkIfInPatientAPI(context).then((res) {
if (res['MessageStatus'] == 1) {
isAdmitted = res['isAdmitted'];
hasAdmissionRequest = res['hasAdmissionRequests'];
print("IS ADMITTED: $isAdmitted");
print("Has Admission Request: $hasAdmissionRequest");
if (isAdmitted) {
if (res['PatientAdmittedInformation'].length != 0) {
getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]);
projectViewModel.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']);
projectViewModel.setInPatientAdmissionInfo(getAdmissionInfoResponseModel);
projectViewModel.setIsPatientAdmitted(true);
}
}
if (hasAdmissionRequest) {
if (res['MedicalInstruction'].length != 0) {
getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]);
// projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['ProjectID']);
projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']);
projectViewModel.setInPatientAdmissionRequest(getAdmissionRequestInfoResponseModel);
projectViewModel.setPatientHasAdmissionRequest(true);
}
}
} else {}
});
}
goToHome() async {
widget.authenticatedUserObject.isLogin = true;
widget.appointmentRateViewModel.isLogin = true;
@ -247,7 +202,6 @@ class _UserLoginAgreementPageState extends State<UserLoginAgreementPage> {
// GifLoaderDialogUtils.hideDialog(context);
getToDoCount();
checkIfIsInPatient();
widget.appointmentRateViewModel
.getIsLastAppointmentRatedList(projectViewModel.isArabic ? 1 : 2)
.then((value) => {

@ -80,8 +80,7 @@ class AskDoctorPage extends StatelessWidget {
doctor: doctorList,
isLiveCareAppointment: false,
isShowFlag: false,
onTap: () async {
if (await checkIfDoctorAvailable(_doctor, context)) {
onTap: () {
GifLoaderDialogUtils.showMyDialog(context);
service.getCallInfoHoursResult(doctorId: _doctor.doctorID, projectId: _doctor.projectID).then((res) {
GifLoaderDialogUtils.hideDialog(context);
@ -96,7 +95,6 @@ class AskDoctorPage extends StatelessWidget {
if (err != null) AppToast.showErrorToast(message: err.toString());
print(err);
});
}
},
);
},
@ -108,32 +106,6 @@ class AskDoctorPage extends StatelessWidget {
);
}
Future<bool> checkIfDoctorAvailable(DoctorList _doctor, BuildContext context) async {
AskDoctorService askDocservice = new AskDoctorService();
bool isAvailable = false;
GifLoaderDialogUtils.showMyDialog(context);
await askDocservice.isDoctorAvailable(doctorId: _doctor.doctorID, projectId: _doctor.projectID, clinicId: _doctor.clinicID).then((res) {
GifLoaderDialogUtils.hideDialog(context);
if (res != null) {
print(res['IsDoctorAvailable']);
if (res['IsDoctorAvailable']) {
isAvailable = true;
} else {
isAvailable = false;
AppToast.showErrorToast(message: res['endUserMessage'], localContext: context);
}
} else {
isAvailable = true;
}
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
if (err != null) AppToast.showErrorToast(message: err.toString(), localContext: context);
print(err);
});
return Future.value(isAvailable);
}
String getDate(String date) {
DateTime dateObj = DateUtil.convertStringToDate(date);
return DateUtil.getWeekDay(dateObj.weekday) +

@ -25,7 +25,6 @@ import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/in_app_browser/InAppBrowser.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
@ -150,22 +149,16 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
)
: Image.asset(getImagePath(widget.selectedPaymentMethod!)),
),
Row(
children: [
widget.advanceModel!.hospitalsModel!.projectOutSA! ? Container() : projectViewModel.isArabic ? Container() : SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 20, height: 20),
mWidth(6),
Text(
widget.advanceModel!.hospitalsModel!.projectOutSA! ? '${widget.advanceModel!.amount} ' + TranslationBase.of(context).aed : '${widget.advanceModel!.amount}',
widget.advanceModel!.hospitalsModel!.projectOutSA!
? '${widget.advanceModel!.amount} ' + TranslationBase.of(context).aed
: '${widget.advanceModel!.amount} ' + TranslationBase.of(context).sar,
// '${widget.advanceModel.amount} ' + TranslationBase.of(context).sar,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w900,
letterSpacing: -0.48,
),
),
mWidth(6),
widget.advanceModel!.hospitalsModel!.projectOutSA! ? Container() : projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 20, height: 20) : Container(),
],
)
],
),
@ -337,8 +330,8 @@ class _ConfirmPaymentPageState extends State<ConfirmPaymentPage> {
currency: projectViewModel.authenticatedUserObject.user.outSA == 1 ? "AED" : "SAR",
onFailed: (failureResult) async {
GifLoaderDialogUtils.hideDialog(context);
log("failureResult: ${failureResult.message.toString()}");
AppToast.showErrorToast(message: failureResult.message.toString());
log("failureResult: ${failureResult.toString()}");
AppToast.showErrorToast(message: failureResult.toString());
},
onSuccess: (successResult) async {
log("Payfort: ${successResult.responseMessage}");

@ -5,7 +5,6 @@ import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart';
import 'package:diplomaticquarterapp/pages/base/base_view.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
@ -96,42 +95,18 @@ class MyBalancePage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
projectViewModel.user!.outSA == 1
? Container()
: projectViewModel.isArabic
? Container()
: SvgPicture.asset(
"assets/images/new/Saudi_Riyal_Symbol.svg",
width: 22,
height: 22,
color: Colors.white,
),
mWidth(6),
Text(
double.parse(model.totalAdvanceBalanceAmount?.toString() ?? "0").toStringAsFixed(2),
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
letterSpacing: -1.44,
height: 24 / 21,
height: 24 / 23,
color: Colors.white,
),
),
mWidth(6),
projectViewModel.isArabic
? SvgPicture.asset(
"assets/images/new/Saudi_Riyal_Symbol.svg",
width: 22,
height: 22,
color: Colors.white,
)
: Container(),
],
),
Text(
projectViewModel.user!.outSA == 1 ? TranslationBase.of(context).aed : "",
projectViewModel.user!.outSA == 1 ? TranslationBase.of(context).aed : TranslationBase.of(context).sar,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
@ -181,16 +156,8 @@ class MyBalancePage extends StatelessWidget {
),
),
),
Row(
children: [
projectViewModel.user!.outSA == 1
? Container()
: projectViewModel.isArabic
? Container()
: SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16),
mWidth(6),
Text(
amount.toStringAsFixed(2) + " " + (projectViewModel.user!.outSA == 1 ? TranslationBase.of(context).aed : ""),
amount.toStringAsFixed(2) + " " + (projectViewModel.user!.outSA == 1 ? TranslationBase.of(context).aed : TranslationBase.of(context).sar),
style: TextStyle(
fontSize: 16,
letterSpacing: -0.64,
@ -198,10 +165,6 @@ class MyBalancePage extends StatelessWidget {
color: Color(0xff2E303A),
),
),
mWidth(6),
projectViewModel.isArabic ? SvgPicture.asset("assets/images/new/Saudi_Riyal_Symbol.svg", width: 16, height: 16) : Container(),
],
),
],
),
);

@ -64,8 +64,6 @@ class _LaboratoryResultPageState extends State<LaboratoryResultPage> {
patientLabOrder: widget.patientLabOrders,
mes: TranslationBase.of(context).sendSuc,
userObj: projectViewModel.user,
languageID: projectViewModel.isArabic ? 1 : 2,
isDownload: true,
isVidaPlus: Utils.isVidaPlusProject(
projectViewModel,
int.parse(widget.patientLabOrders!.projectID!),
@ -120,6 +118,14 @@ class _LaboratoryResultPageState extends State<LaboratoryResultPage> {
);
}
Future<String> _createFileFromString(String encodedStr, String ext) async {
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getApplicationDocumentsDirectory()).path;
File file = File("$dir/" + DateTime.now().millisecondsSinceEpoch.toString() + "." + ext);
await file.writeAsBytes(bytes);
return file.path;
}
String getSpecialResults(LabsViewModel model) {
String labResults = "";
model.patientLabSpecialResult.forEach((element) {

@ -151,7 +151,7 @@ class _InvoiceDetailState extends State<InvoiceDetail> {
child: _getNormalText(TranslationBase.of(context).discount),
),
Expanded(
child: _getNormalText(this.totalDiscount.toString(), isBold: true),
child: _getNormalText(this.totalDiscount.toString() + " " + TranslationBase.of(context).sar, isBold: true),
)
],
),
@ -169,7 +169,7 @@ class _InvoiceDetailState extends State<InvoiceDetail> {
"%): "),
),
Expanded(
child: _getNormalText(num.tryParse(this.totalVAT.toString())!.toStringAsFixed(2), isBold: true),
child: _getNormalText(num.tryParse(this.totalVAT.toString())!.toStringAsFixed(2) + " " + TranslationBase.of(context).sar, isBold: true),
)
],
),
@ -184,7 +184,7 @@ class _InvoiceDetailState extends State<InvoiceDetail> {
child: _getNormalText(TranslationBase.of(context).total),
),
Expanded(
child: _getNormalText(this.subTotal.toString(), isBold: true),
child: _getNormalText(this.subTotal.toString() + " " + TranslationBase.of(context).sar, isBold: true),
)
],
),
@ -199,7 +199,7 @@ class _InvoiceDetailState extends State<InvoiceDetail> {
child: _getNormalText(TranslationBase.of(context).paid),
),
Expanded(
child: _getNormalText(this.grandTotal.toString(), isBold: true),
child: _getNormalText(this.grandTotal.toString() + " " + TranslationBase.of(context).sar, isBold: true),
)
],
),
@ -283,9 +283,9 @@ class _InvoiceDetailState extends State<InvoiceDetail> {
isLast: i == (widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation!.length - 1), mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation![i].quantity}',
isLast: i == (widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation!.length - 1), mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation![i].price.toString()}',
Utils.tableColumnValue('${widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation![i].price.toString() + " " + TranslationBase.of(context).sar}',
isLast: i == (widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation!.length - 1), mProjectViewModel: projectViewModel),
Utils.tableColumnValue('${widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation![i].total.toString()}',
Utils.tableColumnValue('${widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation![i].total.toString() + " " + TranslationBase.of(context).sar}',
isLast: i == (widget.dentalInvoiceDetailResponse.listEInvoiceForDental![0].listConsultation!.length - 1), mProjectViewModel: projectViewModel),
]),
);

@ -1476,7 +1476,7 @@ class DoctorsListService extends BaseService {
Future<Map> HIS_createAdvancePayment(AppoitmentAllHistoryResultList appo, String projectID, double payedAmount, String paymentReference, String paymentMethodName, dynamic patientType,
String patientName, dynamic patientID, BuildContext context,
{bool isAncillaryOrder = false, int clinicID = 0}) async {
{bool isAncillaryOrder = false, int clinicID = 0, dynamic orderNo, dynamic appointmentID, List<dynamic> selectedProcListAPI = const []}) async {
Map<String, dynamic> request;
if (await this.sharedPref.getObject(USER_PROFILE) != null) {
var data = AuthenticatedUser.fromJson(await this.sharedPref.getObject(USER_PROFILE));
@ -1510,7 +1510,12 @@ class DoctorsListService extends BaseService {
"PatientTypeID": patientType,
"IsAncillaryOrder": isAncillaryOrder,
// "AncillaryProcedureList": ancillaryOrdersProcedureList,
"PatientType": patientType
"PatientType": patientType,
"RequestAncillaryOrderInvoice": isAncillaryOrder
? [
{"MemberID": 102, "ProjectID": projectID, "AppointmentNo": appointmentID, "OrderNo": orderNo, "AncillaryOrderInvoiceProcList": selectedProcListAPI}
]
: [],
};
dynamic localRes;
await baseAppClient.post(HIS_CREATE_ADVANCE_PAYMENT, onSuccess: (response, statusCode) async {
@ -1881,7 +1886,8 @@ class DoctorsListService extends BaseService {
return Future.value(localRes);
}
Future<Map> autoGenerateInvoiceERClinic(int? projectID, int? paymentMethod, String? paymentReferenceNo, num? amount, String? cardType, String? cardNumber, String? orderID, String? rrn, bool isAdvanceAvailable) async {
Future<Map> autoGenerateInvoiceERClinic(
int? projectID, int? paymentMethod, String? paymentReferenceNo, num? amount, String? cardType, String? cardNumber, String? orderID, String? rrn, bool isAdvanceAvailable) async {
Map<String, dynamic> request;
request = {
"ProjectID": projectID,
@ -1995,4 +2001,23 @@ class DoctorsListService extends BaseService {
return Future.value(localRes);
}
Future<Map> getLabQueueNumber(int projectID, int patientID, bool isVidaPlus, String invoiceNo, String orderNo) async {
Map<String, dynamic> request;
request = {
"LanguageID": 1,
"QLineLabPatientCallNoGetModel": {"projectID": projectID, "patientID": patientID, "isVidaPlus": isVidaPlus, "invoiceNo": invoiceNo, "orderNo": orderNo}
};
hasError = false;
dynamic localRes;
await baseAppClient.post(GET_PATIENT_LAB_QUEUE_NUMBER, onSuccess: (dynamic response, int statusCode) {
localRes = response;
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
}, body: request);
return Future.value(localRes);
}
}

@ -1777,7 +1777,7 @@ class AuthProvider with ChangeNotifier {
Future<dynamic> checkIfUserAgreed() async {
Map<String, dynamic> request;
request = {"Region": 1, "SessionID": SESSION_ID};
request = {"Region": 1};
dynamic localRes;
try {
await new BaseAppClient().post(CHECK_USAGE_AGREEMENT, onSuccess: (dynamic response, int statusCode) {

@ -184,13 +184,12 @@ class ClinicListService extends BaseService {
return Future.value(localRes);
}
Future<Map> getInPatientPaymentLink(int paymentRequestID, int projectID, int admissionNo, int orderID, String name, String email, num amount, String nationalID, int clinicID, context) async {
Future<Map> getInPatientPaymentLink(int projectID, int admissionNo, int orderID, String name, String email, num amount, String nationalID, int clinicID, context) async {
Map<String, dynamic> request;
// request = {"ProjectID": projectID, "AdmissionReqNo": admissionReqNo, "AdmissionNo": admissionNo};
request = {
"ProjectID": projectID,
"PaymentRequestId": paymentRequestID,
"ClientOrderID": orderID,
"OrderDescription": "InPatient Advance Payment",
"CustomerName": name,
@ -429,7 +428,7 @@ class ClinicListService extends BaseService {
localRes = response;
}, onFailure: (String error, int statusCode) {
throw error;
}, body: request, isAllowAny: true);
}, body: request);
return Future.value(localRes);
}

@ -18,12 +18,11 @@ class LocationUtils {
AppSharedPreferences sharedPref = new AppSharedPreferences();
bool isShowConfirmDialog;
bool isShowLocationTimeoutDialog;
BuildContext context;
bool isHuawei;
final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance;
LocationUtils({required this.isShowConfirmDialog, required this.context, this.isHuawei = false, this.isShowLocationTimeoutDialog = true});
LocationUtils({required this.isShowConfirmDialog, required this.context, this.isHuawei = false});
void getCurrentLocation({Function(LatLng)? callBack}) async {
if (Platform.isAndroid && isHuawei) {
@ -33,15 +32,12 @@ class LocationUtils {
if (value) {
await Geolocator.checkPermission().then((permission) async {
if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) {
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 5)).then((value) {
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best, timeLimit: Duration(seconds: 5)).then((value) {
setLocation(value);
if (callBack != null) callBack(LatLng(value.latitude, value.longitude));
}).catchError((err) {
print(err);
if (isShowConfirmDialog && isShowLocationTimeoutDialog)
showLocationTimeOutDialog(failureCallBack: () {
Geolocator.openAppSettings();
});
if (isShowConfirmDialog) showLocationTimeOutDialog(failureCallBack: (){});
});
}
@ -134,9 +130,7 @@ class LocationUtils {
accuracy: 1.0,
heading: 0.0,
speed: 0.0,
speedAccuracy: 1,
altitudeAccuracy: 0.0,
headingAccuracy: 0.0,
speedAccuracy: 1, altitudeAccuracy: 0.0, headingAccuracy: 0.0,
// altitudeAccuracy: 0.0,
// headingAccuracy: 0.0,
// altitudeAccuracy: 0,

@ -62,7 +62,6 @@ class TranslationBase {
String get hospitalName => localizedValues['hospitalName'][locale.languageCode];
String get doctorName => localizedValues['doctorName'][locale.languageCode];
String get NoClinicFound => localizedValues['NoClinicFound'][locale.languageCode];
String get nearestAppo => localizedValues['nearestAppo'][locale.languageCode];
@ -1137,7 +1136,6 @@ class TranslationBase {
String get myPrescription => localizedValues['myPrescription'][locale.languageCode];
String get quantity => localizedValues['quantity'][locale.languageCode];
String get productQuantity => localizedValues['productQuantity'][locale.languageCode];
String get conditionsHMG => localizedValues['conditionsHMG'][locale.languageCode];
@ -1485,7 +1483,6 @@ class TranslationBase {
String get enablingWifi => localizedValues['enablingWifi'][locale.languageCode];
String get offerAndPackages => localizedValues['offerAndPackages'][locale.languageCode];
String get orderHistory => localizedValues['orderHistory'][locale.languageCode];
String get offerAndPackagesDetails => localizedValues['offerAndPackagesDetails'][locale.languageCode];
@ -1857,7 +1854,6 @@ class TranslationBase {
String get needPrescription => localizedValues['needPrescription'][locale.languageCode];
String get outOfStockMsg => localizedValues['outOfStockMsg'][locale.languageCode];
String get productOutOfStock => localizedValues['productOutOfStock'][locale.languageCode];
String get noArabicLetters => localizedValues['noArabicLetters'][locale.languageCode];
@ -2820,454 +2816,235 @@ class TranslationBase {
String get submitReview => localizedValues["submitReview"][locale.languageCode];
String get Protein => localizedValues["Protein"][locale.languageCode];
String get Cals => localizedValues["Cals"][locale.languageCode];
String get gramsPerDay => localizedValues["gramsPerDay"][locale.languageCode];
String get gr => localizedValues["gr"][locale.languageCode];
String get gramsPerMeal => localizedValues["gramsPerMeal"][locale.languageCode];
String get cancelReminder => localizedValues["CancelReminder"][locale.languageCode];
String get reminderCancelSuccess => localizedValues["reminderCancelSuccess"][locale.languageCode];
String get syncSuccess => localizedValues["syncSuccess"][locale.languageCode];
String get useLakumPoints => localizedValues["useLakumPoints"][locale.languageCode];
String get points => localizedValues["points"][locale.languageCode];
String get availableBalance => localizedValues["availableBalance"][locale.languageCode];
String get ordersDashboard => localizedValues["ordersDashboard"][locale.languageCode];
String get requestedDateLiveCare => localizedValues["requestedDateLiveCare"][locale.languageCode];
String get yourTurn => localizedValues["yourTurn"][locale.languageCode];
String get patients => localizedValues["patients"][locale.languageCode];
String get group => localizedValues["group"][locale.languageCode];
String get ancillaryOrdersPaymentConfirm => localizedValues["ancillaryOrdersPaymentConfirm"][locale.languageCode];
String get covidTestTodo => localizedValues["covidTestTodo"][locale.languageCode];
String get successRegister => localizedValues["successRegister"][locale.languageCode];
String get pharmacyLiveCare => localizedValues["pharmacyLiveCare"][locale.languageCode];
String get ancillaryOrderPaymentSuccess => localizedValues["ancillaryOrderPaymentSuccess"][locale.languageCode];
String get connectTitle => localizedValues["connectTitle"][locale.languageCode];
String get connectSubtitle => localizedValues["connectSubtitle"][locale.languageCode];
String get declineLbl => localizedValues["declineLbl"][locale.languageCode];
String get covidConsent => localizedValues["covidConsent"][locale.languageCode];
String get covidConsentHeader => localizedValues["covidConsentHeader"][locale.languageCode];
String get drawOverAppsPermission => localizedValues["drawOverAppsPermission"][locale.languageCode];
String get selectTamaraPlan => localizedValues["selectTamaraPlan"][locale.languageCode];
String get installments => localizedValues["installments"][locale.languageCode];
String get cameraPermissionDialog => localizedValues["cameraPermissionDialog"][locale.languageCode];
String get galleryPermission => localizedValues["galleryPermission"][locale.languageCode];
String get locationPermissionDialog => localizedValues["locationPermissionDialog"][locale.languageCode];
String get calendarPermission => localizedValues["calendarPermission"][locale.languageCode];
String get recordAudioPermission => localizedValues["recordAudioPermission"][locale.languageCode];
String get wifiPermission => localizedValues["wifiPermission"][locale.languageCode];
String get physicalActivityPermission => localizedValues["physicalActivityPermission"][locale.languageCode];
String get bluetoothPermission => localizedValues["bluetoothPermission"][locale.languageCode];
String get privacyPolicy => localizedValues["privacyPolicy"][locale.languageCode];
String get termsConditions => localizedValues["termsConditions"][locale.languageCode];
String get liveCarePermissions => localizedValues["liveCarePermissions"][locale.languageCode];
String get prescriptionDeliveryError => localizedValues["prescriptionDeliveryError"][locale.languageCode];
String get lakumUnhold => localizedValues["lakumUnhold"][locale.languageCode];
String get lakumDiscontinue => localizedValues["lakumDiscontinue"][locale.languageCode];
String get lakumSuccess => localizedValues["lakumSuccess"][locale.languageCode];
String get deleteAccount => localizedValues["deleteAccount"][locale.languageCode];
String get deactivateAccount => localizedValues["deactivateAccount"][locale.languageCode];
String get accountDeactivated => localizedValues["accountDeactivated"][locale.languageCode];
String get accountDeactivatedMsg => localizedValues["accountDeactivatedMsg"][locale.languageCode];
String get updateInsuranceManually => localizedValues["updateInsuranceManually"][locale.languageCode];
String get enterInsuranceDetails => localizedValues["enterInsuranceDetails"][locale.languageCode];
String get cardHolderName => localizedValues["cardHolderName"][locale.languageCode];
String get membershipNo => localizedValues["membershipNo"][locale.languageCode];
String get insurancePolicyNo => localizedValues["policyNo"][locale.languageCode];
String get insuranceClassName => localizedValues["insuranceClassName"][locale.languageCode];
String get NFCNotSupported => localizedValues["NFCNotSupported"][locale.languageCode];
String get paymentOnly => localizedValues["paymentOnly"][locale.languageCode];
String get pendingOnly => localizedValues["pendingOnly"][locale.languageCode];
String get insuranceRequestSubmit => localizedValues["insuranceRequestSubmit"][locale.languageCode];
String get enterWorkplaceName => localizedValues["enter-workplace-name"][locale.languageCode];
String get workplaceName => localizedValues["workplaceName"][locale.languageCode];
String get needApproval => localizedValues["needApproval"][locale.languageCode];
String get callLiveCareSupport => localizedValues["callLiveCareSupport"][locale.languageCode];
String get pendingActivation => localizedValues["pendingActivation"][locale.languageCode];
String get awaitingApproval => localizedValues["awaitingApproval"][locale.languageCode];
String get liveCareSupportContact => localizedValues["liveCareSupportContact"][locale.languageCode];
String get scanNFC => localizedValues["scanNFC"][locale.languageCode];
String get pharmaLiveCare => localizedValues["pharmaLiveCare"][locale.languageCode];
String get pharmaLiveCare1 => localizedValues["pharmaLiveCare1"][locale.languageCode];
String get pharmaLiveCareDesc1 => localizedValues["pharmaLiveCareDesc1"][locale.languageCode];
String get wherePharmaLiveCare => localizedValues["wherePharmaLiveCare"][locale.languageCode];
String get pharmaLiveCareDesc2 => localizedValues["pharmaLiveCareDesc2"][locale.languageCode];
String get howPharmaLiveCare => localizedValues["howPharmaLiveCare"][locale.languageCode];
String get pharmaLiveCareDesc3 => localizedValues["pharmaLiveCareDesc3"][locale.languageCode];
String get pharmaLiveCareScanQR => localizedValues["pharmaLiveCareScanQR"][locale.languageCode];
String get pharmaLiveCareScanQR1 => localizedValues["pharmaLiveCareScanQR1"][locale.languageCode];
String get pharmaLiveCareMakePayment => localizedValues["pharmaLiveCareMakePayment"][locale.languageCode];
String get pharmaLiveCareMakePayment1 => localizedValues["pharmaLiveCareMakePayment1"][locale.languageCode];
String get pharmaLiveCareJoinConsultation => localizedValues["pharmaLiveCareJoinConsultation"][locale.languageCode];
String get pharmaLiveCareJoinConsultation1 => localizedValues["pharmaLiveCareJoinConsultation1"][locale.languageCode];
String get emergencyServicesSubtitle => localizedValues["emergencyServicesSubtitle"][locale.languageCode];
String get rateDoctorResponse => localizedValues["rateDoctorResponse"][locale.languageCode];
String get comments => localizedValues["comments"][locale.languageCode];
String get rateDoctorResponseHeading => localizedValues["rateDoctorResponseHeading"][locale.languageCode];
String get updateInsuranceManuallyDialog => localizedValues["updateInsuranceManuallyDialog"][locale.languageCode];
String get viewReport => localizedValues["viewReport"][locale.languageCode];
String get sickLeaveAdmittedPatient => localizedValues["sickLeaveAdmittedPatient"][locale.languageCode];
String get InPatient => localizedValues["InPatient"][locale.languageCode];
String get inPatientServices => localizedValues["InPatientServices"][locale.languageCode];
String get InPatientServicesHeader => localizedValues["InPatientServicesHeader"][locale.languageCode];
String get admissionGeneral => localizedValues["admissionGeneral"][locale.languageCode];
String get consent => localizedValues["consent"][locale.languageCode];
String get generalInstructionsTitle => localizedValues["generalInstructionsTitle"][locale.languageCode];
String get generalInstructionsSubTitle => localizedValues["generalInstructionsSubTitle"][locale.languageCode];
String get medicalInstructionsTitle => localizedValues["medicalInstructionsTitle"][locale.languageCode];
String get medicalInstructionsSubTitle => localizedValues["medicalInstructionsSubTitle"][locale.languageCode];
String get mealPlanTitle => localizedValues["mealPlanTitle"][locale.languageCode];
String get mealPlanSubTitle => localizedValues["mealPlanSubTitle"][locale.languageCode];
String get birthNotificationTitle => localizedValues["birthNotificationTitle"][locale.languageCode];
String get birthNotificationSubTitle => localizedValues["birthNotificationSubTitle"][locale.languageCode];
String get admissionNoticeTitle => localizedValues["admissionNoticeTitle"][locale.languageCode];
String get admissionNoticeSubTitle => localizedValues["admissionNoticeSubTitle"][locale.languageCode];
String get mothersMRN => localizedValues["mothersMRN"][locale.languageCode];
String get mothersName => localizedValues["mothersName"][locale.languageCode];
String get fathersNameEN => localizedValues["fathersNameEN"][locale.languageCode];
String get fathersNameAR => localizedValues["fathersNameAR"][locale.languageCode];
String get babysNameEN => localizedValues["babysNameEN"][locale.languageCode];
String get babysNameAR => localizedValues["babysNameAR"][locale.languageCode];
String get contactNumber => localizedValues["contactNumber"][locale.languageCode];
String get scanID => localizedValues["scanID"][locale.languageCode];
String get birthNotificationNotes1 => localizedValues["birthNotificationNotes1"][locale.languageCode];
String get birthNotificationNotes2 => localizedValues["birthNotificationNotes2"][locale.languageCode];
String get birthNotificationNotes3 => localizedValues["birthNotificationNotes3"][locale.languageCode];
String get placeOrder => localizedValues["placeOrder"][locale.languageCode];
String get isFasting => localizedValues["isFasting"][locale.languageCode];
String get noGeneralInstructions => localizedValues["noGeneralInstructions"][locale.languageCode];
String get noMedicalInstructions => localizedValues["noMedicalInstructions"][locale.languageCode];
String get medicalInstructions => localizedValues["medicalInstructions"][locale.languageCode];
String get generalInstructions => localizedValues["generalInstructions"][locale.languageCode];
String get copyLink => localizedValues["copyLink"][locale.languageCode];
String get copyLinkTxt => localizedValues["copyLinkTxt"][locale.languageCode];
String get paymentLinkCopied => localizedValues["paymentLinkCopied"][locale.languageCode];
String get proErrorMessage => localizedValues["proErrorMessage"][locale.languageCode];
String get admissionNo => localizedValues["admissionNo"][locale.languageCode];
String get admissionReqNo => localizedValues["admissionReqNo"][locale.languageCode];
String get dischargeDate => localizedValues["dischargeDate"][locale.languageCode];
String get selectAdmissionText => localizedValues["selectAdmissionText"][locale.languageCode];
String get onlyAdmitted => localizedValues["onlyAdmitted"][locale.languageCode];
String get assistYou => localizedValues["assistYou"][locale.languageCode];
String get receive => localizedValues["receive"][locale.languageCode];
String get PRO => localizedValues["PRO"][locale.languageCode];
String get patientRelationOffice => localizedValues["patientRelationOffice"][locale.languageCode];
String get roomNo => localizedValues["roomNo"][locale.languageCode];
String get generalConsent => localizedValues["generalConsent"][locale.languageCode];
String get generalConsent1 => localizedValues["generalConsent1"][locale.languageCode];
String get hospitalRules => localizedValues["hospitalRules"][locale.languageCode];
String get generalConsent2 => localizedValues["generalConsent2"][locale.languageCode];
String get communicationConsent => localizedValues["communicationConsent"][locale.languageCode];
String get generalConsent3 => localizedValues["generalConsent3"][locale.languageCode];
String get releaseConsent => localizedValues["releaseConsent"][locale.languageCode];
String get generalConsent4 => localizedValues["generalConsent4"][locale.languageCode];
String get generalConsent5 => localizedValues["generalConsent5"][locale.languageCode];
String get valuables => localizedValues["valuables"][locale.languageCode];
String get generalConsent6 => localizedValues["generalConsent6"][locale.languageCode];
String get financialConsent => localizedValues["financialConsent"][locale.languageCode];
String get generalConsent7 => localizedValues["generalConsent7"][locale.languageCode];
String get dataSharingConsent => localizedValues["dataSharingConsent"][locale.languageCode];
String get generalConsent8 => localizedValues["generalConsent8"][locale.languageCode];
String get permissionLeaveConsent => localizedValues["permissionLeaveConsent"][locale.languageCode];
String get generalConsent9 => localizedValues["generalConsent9"][locale.languageCode];
String get observeConsent => localizedValues["observeConsent"][locale.languageCode];
String get generalConsent10 => localizedValues["generalConsent10"][locale.languageCode];
String get noGuaranteeConsent => localizedValues["noGuaranteeConsent"][locale.languageCode];
String get generalConsent11 => localizedValues["generalConsent11"][locale.languageCode];
String get disputeConsent => localizedValues["disputeConsent"][locale.languageCode];
String get generalConsent12 => localizedValues["generalConsent12"][locale.languageCode];
String get patientsRightsConsent => localizedValues["patientsRightsConsent"][locale.languageCode];
String get generalConsent13 => localizedValues["generalConsent13"][locale.languageCode];
String get acknowledgementConsent => localizedValues["acknowledgementConsent"][locale.languageCode];
String get generalConsent14 => localizedValues["generalConsent14"][locale.languageCode];
String get invalidEligibility => localizedValues["invalidEligibility"][locale.languageCode];
String get invalidInsurance => localizedValues["invalidInsurance"][locale.languageCode];
String get continueCash => localizedValues["continueCash"][locale.languageCode];
String get updateInsuranceText => localizedValues["updateInsurance"][locale.languageCode];
String get downloadReport => localizedValues["downloadReport"][locale.languageCode];
String get habibCallCenter => localizedValues["habibCallCenter"][locale.languageCode];
String get cashAmountUpdateInsurance => localizedValues["cashAmountUpdateInsurance"][locale.languageCode];
String get validInsurance => localizedValues["validInsurance"][locale.languageCode];
String get contactRRT => localizedValues["contactRRT"][locale.languageCode];
String get checkInViaLocation => localizedValues["checkInViaLocation"][locale.languageCode];
String get locationCheckInError => localizedValues["locationCheckInError"][locale.languageCode];
String get upcoming => localizedValues["upcoming"][locale.languageCode];
String get noUpcomingAppointment => localizedValues["noUpcomingAppointment"][locale.languageCode];
String get locationTimeoutError => localizedValues["locationTimeoutError"][locale.languageCode];
String get loadMore => localizedValues["loadMore"][locale.languageCode];
String get selectHospitalBloodDonation => localizedValues["selectHospitalBloodDonation"][locale.languageCode];
String get wecare => localizedValues["wecare"][locale.languageCode];
String get myinstructions => localizedValues["myinstructions"][locale.languageCode];
String get clinicLocation => localizedValues["clinicLocation"][locale.languageCode];
String get waitingAppointment => localizedValues["waitingAppointment"][locale.languageCode];
String get whatWaitingAppointment => localizedValues["whatWaitingAppointment"][locale.languageCode];
String get waitingAppointmentText1 => localizedValues["waitingAppointmentText1"][locale.languageCode];
String get waitingAppointmentText2 => localizedValues["waitingAppointmentText2"][locale.languageCode];
String get waitingAppointmentText3 => localizedValues["waitingAppointmentText3"][locale.languageCode];
String get waitingAppointmentVerificationMethod => localizedValues["waitingAppointmentVerificationMethod"][locale.languageCode];
String get howToUseVerificationMethod => localizedValues["howToUseVerificationMethod"][locale.languageCode];
String get addToWaitingList => localizedValues["addToWaitingList"][locale.languageCode];
String get searchClinic => localizedValues["searchClinic"][locale.languageCode];
String get enterMobileNumber => localizedValues["enterMobileNumber"][locale.languageCode];
String get videoCall => localizedValues["videoCall"][locale.languageCode];
String get audioCall => localizedValues["audioCall"][locale.languageCode];
String get phoneCall => localizedValues["phoneCall"][locale.languageCode];
String get selectCallType => localizedValues["selectCallType"][locale.languageCode];
String get selectedCallType => localizedValues["selectedCallType"][locale.languageCode];
String get selectBranch => localizedValues["selectBranch"][locale.languageCode];
String get searchByBranch => localizedValues["searchByBranch"][locale.languageCode];
String get existingPackage => localizedValues["existingPackage"][locale.languageCode];
String get continueOrbookNew => localizedValues["continueOrbookNew"][locale.languageCode];
String get newAppointment => localizedValues["newAppointment"][locale.languageCode];
String get proceedPackage => localizedValues["proceedPackage"][locale.languageCode];
String get hospitalNavigationTitle => localizedValues["hospitalNavigationTitle"][locale.languageCode];
String get hospitalNavigationSubtitle => localizedValues["hospitalNavigationSubtitle"][locale.languageCode];
String get workplaceNameAr => localizedValues["workplaceNameAr"][locale.languageCode];
String get occupationNameEn => localizedValues["occupationNameEn"][locale.languageCode];
String get occupationNameAr => localizedValues["occupationNameAr"][locale.languageCode];
String get continueAgreeTerms => localizedValues["continueAgreeTerms"][locale.languageCode];
String get agreeText => localizedValues["agreeText"][locale.languageCode];
String get ERCheckInSuccess => localizedValues["ERCheckInSuccess"][locale.languageCode];
String get generalConsentTitle => localizedValues["generalConsentTitle"][locale.languageCode];
String get generalConsentSubTitle => localizedValues["generalConsentSubTitle"][locale.languageCode];
String get incorrectNationalId => localizedValues["incorrectNationalId"][locale.languageCode];
String get resultStatus => localizedValues["resultStatus"][locale.languageCode];
String get labResultFlag => localizedValues["labResultFlag"][locale.languageCode];
String get selectOccupation => localizedValues["selectOccupation"][locale.languageCode];
String get selectOccupationError => localizedValues["selectOccupationError"][locale.languageCode];
String get whatIsOnlineCheckIn => localizedValues["whatIsOnlineCheckIn"][locale.languageCode];
String get EROnlineCheckInDesc1 => localizedValues["EROnlineCheckInDesc1"][locale.languageCode];
String get EROnlineCheckInHow => localizedValues["EROnlineCheckInHow"][locale.languageCode];
String get EROnlineCheckInTapOn => localizedValues["EROnlineCheckInTapOn"][locale.languageCode];
String get EROnlineCheckInTapOnCheckIn => localizedValues["EROnlineCheckInTapOnCheckIn"][locale.languageCode];
String get EROnlineCheckInHoldPhone => localizedValues["EROnlineCheckInHoldPhone"][locale.languageCode];
String get EROnlineCheckInHoldPhoneInstruction => localizedValues["EROnlineCheckInHoldPhoneInstruction"][locale.languageCode];
String get EROnlineCheckInWaitTurn => localizedValues["EROnlineCheckInWaitTurn"][locale.languageCode];
String get EROnlineCheckInWaitTurnInstruction => localizedValues["EROnlineCheckInWaitTurnInstruction"][locale.languageCode];
String get download => localizedValues["download"][locale.languageCode];
String get share => localizedValues["share"][locale.languageCode];
String get ancillaryOrderCheckInSuccess => localizedValues["ancillaryOrderCheckInSuccess"][locale.languageCode];
}
class TranslationBaseDelegate extends LocalizationsDelegate<TranslationBase> {

@ -41,7 +41,6 @@ import 'package:diplomaticquarterapp/pages/medical/vital_sign/vital_sign_details
import 'package:diplomaticquarterapp/pages/vaccine/my_vaccines_screen.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/data_display/medical/medical_profile_item.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/alert_dialog.dart';
import 'package:diplomaticquarterapp/widgets/dialogs/covid_consent_dialog.dart';
@ -825,26 +824,19 @@ class Utils {
);
}
static Widget tableColumnValue(String text, {bool isLast = false, bool isCapitable = true, bool isHighLow = false, bool isCurrency = false, required ProjectViewModel mProjectViewModel}) {
static Widget tableColumnValue(String text, {bool isLast = false, bool isCapitable = true, bool isHighLow = false, required ProjectViewModel mProjectViewModel}) {
ProjectViewModel projectViewModel = mProjectViewModel ?? Provider.of(AppGlobal.context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(height: 12),
Row(
children: [
Expanded(
child: Text(
Text(
isCapitable && !projectViewModel.isArabic ? text.toLowerCase().capitalizeFirstofEach : text,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: isHighLow ? CustomColors.accentColor : Color(0xff575757), letterSpacing: -0.4, height: 16 / 10),
),
),
isCurrency ? getSaudiRiyalSymbol() : Container(),
],
),
SizedBox(height: 12),
if (!isLast)
Divider(
@ -971,10 +963,6 @@ class Utils {
return projectDetailListModel;
}
static Widget getSaudiRiyalSymbol({double fontSize = 16}) {
return Text(" SAR ", style: TextStyle(fontFamily: "SaudiRiyal", fontSize: fontSize));
}
//static String generateSignature() {}
}
@ -1044,26 +1032,6 @@ extension StringExtension on String {
}
}
extension TextToRichTextWithIcon on Text {
RichText toRichTextWithIcon() {
// Create the base TextSpan with the text data and style from the Text widget
return RichText(
text: TextSpan(
style: this.style, // Inherit the text style
children: [
WidgetSpan(
child: Text(" SAR ", style: TextStyle(fontFamily: "SaudiRiyal")),
),
TextSpan(
text: this.data, // Add the original text
style: this.style, // Inherit the text style
),
],
),
);
}
}
/*
userBoard.asMap().map((i, element) => MapEntry(i, Stack(
GestureDetector(onTap: () {

@ -24,9 +24,7 @@ class WhatsappMethodChannel {
Future<String> startListening() async {
try{
String code = await _channel.invokeMethod("startListening");
print("the code in flutter is ${code}");
return code;
return await _channel.invokeMethod("startListening");
}catch(e){
return "";
}

@ -1,70 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:vital_sign_camera/vital_sign_camera.dart';
//
// class VitalSigns extends StatefulWidget {
// const VitalSigns({super.key});
//
// @override
// State<VitalSigns> createState() => _VitalSignState();
// }
//
// class _VitalSignState extends State<VitalSigns> {
// late final VitalSignCameraController _vitalSignCameraController;
// late Future<CameraDevice?> cameraDevice;
//
// @override
// void initState() {
// super.initState();
// cameraDevice = getFrontCamera();
// }
//
// double? _heartRate;
//
// Future<CameraDevice?> getFrontCamera() async {
// if (CameraPermissionStatus.authorized != await requestCameraPermission()) {
// return null;
// }
// return queryCameraDevice(CameraPosition.front);
// }
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// body: Stack(children: [
// VitalSignCamera(
// onCreated: _onVitalSignCameraCreated,
// isActive: true,
// userInfo: UserInfo(
// age: 30, gender: Gender.male, userId: '__YOUR_USER_ID__'),
// config: VitalSignCameraConfig(apiKey: '__YOUR_API_KEY__'),
// device: cameraDevice,
// onVideoFrameProcessed: _onVideoFrameProcessed),
// Center(
// child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// ElevatedButton(
// onPressed: () {
// setState(() {
// _vitalSignCameraController.startScanning();
// });
// },
// child: const Text('start')),
// Text('Heart rate: $_heartRate'),
// ],
// ),
// ),
// ]),
// );
// }
//
// void _onVideoFrameProcessed(VideoFrameProcessedEvent event) {
// // setState(() {
// // _heartRate = event.healthResult?.health?.vitalSigns.heartRate;
// // });
// }
//
// void _onVitalSignCameraCreated(VitalSignCameraController controller) {
// _vitalSignCameraController = controller;
// }
// }

@ -20,15 +20,13 @@ class BottomNavigationItem extends StatelessWidget {
final String? name;
final bool? isDisabled;
late ToDoCountProviderModel toDoProvider;
AuthenticatedUserObject authenticatedUserObject = locator<AuthenticatedUserObject>();
BottomNavigationItem({this.icon, this.activeIcon, this.changeIndex, this.index, this.currentIndex, this.name, this.isDisabled = false});
@override
Widget build(BuildContext context) {
toDoProvider = Provider.of<ToDoCountProviderModel>(context);
var model = Provider.of<ToDoCountProviderModel>(context);
ProjectViewModel projectViewModel = Provider.of(context);
return Expanded(
child: SizedBox(
@ -74,7 +72,7 @@ class BottomNavigationItem extends StatelessWidget {
),
],
)
: (authenticatedUserObject.isLogin && toDoProvider.isShowBadge)
: (authenticatedUserObject.isLogin && model.isShowBadge)
? Stack(
alignment: AlignmentDirectional.center,
children: [
@ -122,7 +120,7 @@ class BottomNavigationItem extends StatelessWidget {
// borderRadius: BorderRadius.circular(8),
badgeContent: Container(
padding: EdgeInsets.all(2.0),
child: Text((toDoProvider.count! + toDoProvider.ancillaryCount!).toString(), style: TextStyle(color: Colors.white, fontSize: 14.0)),
child: Text((model.count! + model.ancillaryCount!).toString(), style: TextStyle(color: Colors.white, fontSize: 14.0)),
),
),
),

@ -67,10 +67,6 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
widget.patientLabOrder!.actualDoctorRate!,
widget.patientLabOrder!.noOfPatientsRate!,
projectViewModel.user.emailAddress!),
buttonTitle: TranslationBase.of(context).download,
buttonIcon: "assets/images/new/download_1.svg",
showConfirmMessageDialog: false,
isDownload: true,
onTap: widget.onTap!,
),
SizedBox(height: 10),

@ -4,7 +4,9 @@ import 'package:diplomaticquarterapp/theme/colors.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/widgets/avatar/large_avatar.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/countdown_timer_controller.dart';
import 'package:flutter_countdown_timer/current_remaining_time.dart';
@ -37,6 +39,8 @@ class DoctorCard extends StatelessWidget {
final bool isLabOrderResult;
final int? resultStatus;
final String? resultStatusDesc;
final bool isAllowCheckInAncillary;
final VoidCallback? onAncillaryCheckInTap;
DoctorCard(
{this.name,
@ -60,7 +64,9 @@ class DoctorCard extends StatelessWidget {
this.projectID = 0,
this.isLabOrderResult = false,
this.resultStatus = 0,
this.resultStatusDesc = ""});
this.resultStatusDesc = "",
this.isAllowCheckInAncillary = false,
this.onAncillaryCheckInTap});
late ProjectViewModel projectViewModel;
@ -68,7 +74,7 @@ class DoctorCard extends StatelessWidget {
Widget build(BuildContext context) {
projectViewModel = Provider.of(context);
return Container(
height: 135,
height: isAllowCheckInAncillary ? 155 : 135,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10.0),
@ -272,6 +278,33 @@ class DoctorCard extends StatelessWidget {
),
],
),
if (isAllowCheckInAncillary)
Column(
children: [
mHeight(5),
InkWell(
onTap: () {
onAncillaryCheckInTap!();
},
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
child: Container(
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 14),
decoration: BoxDecoration(
color: CustomColors.accentColor,
border: Border.all(color: Colors.white, width: 1),
borderRadius: BorderRadius.circular(6),
),
child: Text(
TranslationBase.of(context).checkinOptions,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: -0.4),
),
),
),
),
],
),
],
),
),

@ -15,8 +15,6 @@ import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.da
import 'package:diplomaticquarterapp/models/Authentication/check_activation_code_response.dart';
import 'package:diplomaticquarterapp/models/Authentication/select_device_imei_res.dart';
import 'package:diplomaticquarterapp/models/FamilyFiles/GetAllSharedRecordByStatusResponse.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_info_response_model.dart';
import 'package:diplomaticquarterapp/models/InPatientServices/get_admission_request_info_response_model.dart';
import 'package:diplomaticquarterapp/pages/Blood/user_agreement_page.dart';
import 'package:diplomaticquarterapp/pages/DrawerPages/notifications/notifications_page.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
@ -702,42 +700,6 @@ class _AppDrawerState extends State<AppDrawer> {
});
}
checkIfIsInPatient(BuildContext context) {
bool isAdmitted = false;
bool hasAdmissionRequest = false;
GetAdmissionInfoResponseModel getAdmissionInfoResponseModel;
GetAdmissionRequestInfoResponseModel getAdmissionRequestInfoResponseModel;
ClinicListService service = new ClinicListService();
service.checkIfInPatientAPI(context).then((res) {
if (res['MessageStatus'] == 1) {
isAdmitted = res['isAdmitted'];
hasAdmissionRequest = res['hasAdmissionRequests'];
print("IS ADMITTED: $isAdmitted");
print("Has Admission Request: $hasAdmissionRequest");
if (isAdmitted) {
if (res['PatientAdmittedInformation'].length != 0) {
getAdmissionInfoResponseModel = GetAdmissionInfoResponseModel.fromJson(res['PatientAdmittedInformation'][0]);
projectProvider?.setInPatientProjectID(res['PatientAdmittedInformation'][0]['ProjectID']);
projectProvider?.setInPatientAdmissionInfo(getAdmissionInfoResponseModel);
projectProvider?.setIsPatientAdmitted(true);
}
}
if (hasAdmissionRequest) {
if (res['MedicalInstruction'].length != 0) {
getAdmissionRequestInfoResponseModel = GetAdmissionRequestInfoResponseModel.fromJson(res['MedicalInstruction'][0]);
// projectViewModel.setInPatientProjectID(res['MedicalInstruction'][0]['ProjectID']);
projectProvider?.setInPatientProjectID(res['MedicalInstruction'][0]['projectId']);
projectProvider?.setInPatientAdmissionRequest(getAdmissionRequestInfoResponseModel);
projectProvider?.setPatientHasAdmissionRequest(true);
}
}
} else {}
}).catchError((err) {
projectProvider?.setIsPatientAdmitted(false);
projectProvider?.setPatientHasAdmissionRequest(false);
});
}
loginAfter(result, context, isMainUser) async {
Utils.hideProgressDialog();
String APNSToken = "";
@ -779,8 +741,6 @@ class _AppDrawerState extends State<AppDrawer> {
await this.sharedPref.remove(APPOINTMENT_HISTORY_MEDICAL);
checkIfIsInPatient(context);
appointmentRateViewModel
.getIsLastAppointmentRatedList(languageID)
.then((value) => {

@ -38,9 +38,9 @@ class MyInAppBrowser extends InAppBrowser {
static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL LIVE
// static String APPLE_PAY_PAYFORT_URL = 'https://hmgwebservices.com/PayFortWebLive/PayFortApi/MakeApplePayRequest'; // Payfort Payment Gateway URL UAT
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWeb/pages/SendPayFortRequest.aspx'; // Payfort Payment Gateway URL UAT
static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://hmgwebservices.com/PayFortWebLive/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL LIVE
// static String SERVICE_URL = 'https://uat.hmgwebservices.com/payfortforvidaplus/pages/SendPayFortRequest.aspx'; //Payfort Payment Gateway URL UAT VIDA PLUS

@ -25,7 +25,6 @@ class DoctorHeader extends StatelessWidget {
final String? buttonIcon;
final bool isNeedToShowButton;
final bool isShowName;
final bool isDownload;
DoctorHeader(
{Key? key,
@ -36,7 +35,6 @@ class DoctorHeader extends StatelessWidget {
this.isShowName = false,
this.buttonIcon,
this.showConfirmMessageDialog = true,
this.isDownload = false,
this.onRatingAndReviewTap})
: super(key: key);
@ -109,9 +107,7 @@ class DoctorHeader extends StatelessWidget {
if (headerModel.nationalityFlagURL != null)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: headerModel.nationalityFlagURL.isNotEmpty && headerModel.nationalityFlagURL != null && headerModel.nationalityFlagURL != 'null'
? Image.network(headerModel.nationalityFlagURL, height: 20)
: SizedBox(),
child: headerModel.nationalityFlagURL.isNotEmpty && headerModel.nationalityFlagURL != null && headerModel.nationalityFlagURL != 'null'? Image.network(headerModel.nationalityFlagURL, height: 20) : SizedBox(),
),
],
)
@ -182,8 +178,7 @@ class DoctorHeader extends StatelessWidget {
child: Container(
padding: EdgeInsets.only(top: 10, bottom: 10, right: 15, left: 15),
decoration: BoxDecoration(
color: isDownload ? CustomColors.green : CustomColors.accentColor,
borderRadius: projectViewModel.isArabic ? BorderRadius.only(topRight: Radius.circular(10)) : BorderRadius.only(topLeft: Radius.circular(10))),
color: Color(0XFFD02127), borderRadius: projectViewModel.isArabic ? BorderRadius.only(topRight: Radius.circular(10)) : BorderRadius.only(topLeft: Radius.circular(10))),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [

@ -103,10 +103,9 @@ class SMSOTP {
child: StatefulBuilder(builder: (context, setState) {
if (displayTime == '') {
startTimer(setState);
if (Platform.isAndroid ) {
if (type == 1) checkSignature();
else if(type == 4) _listenWhatsAppCode();
}
// startLister();
if (Platform.isAndroid && type == 1) checkSignature();
}
return Container(
@ -298,15 +297,17 @@ class SMSOTP {
SmsVerification.stopListening();
// });
});
}
void _listenWhatsAppCode(){
WhatsappMethodChannel().startListening().then((message) {
// setState(() {
final intRegex = RegExp(r'\d+', multiLine: true);
var otp = SmsVerification.getCode(message, intRegex);
_pinPutController.text = otp;
onSuccess(otp);
SmsVerification.stopListening();
// });
});
}
// startLister() {

@ -233,7 +233,7 @@ class OTPWidgetState extends State<OTPWidget> with SingleTickerProviderStateMixi
height: widget.pinBoxHeight,
child: TextField(
autofocus: !kIsWeb ? widget.autoFocus : false,
enableInteractiveSelection: false,
enableInteractiveSelection: true,
focusNode: focusNode,
controller: widget.controller,
keyboardType: widget.keyboardType,
@ -260,7 +260,7 @@ class OTPWidgetState extends State<OTPWidget> with SingleTickerProviderStateMixi
border: InputBorder.none,
),
cursorColor: Colors.transparent,
showCursor: false,
showCursor: true,
maxLength: widget.maxLength,
onChanged: _onTextChanged,
),

@ -1 +0,0 @@
TODO: Add your license here.

@ -1,4 +0,0 @@
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

@ -1,9 +0,0 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.cxx

@ -1,69 +0,0 @@
group 'ai.panoptic.vital_sign_camera'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.5.20'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 24
}
}
dependencies {
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.camera:camera-core:1.0.2'
implementation 'com.google.mlkit:face-detection:16.1.2'
implementation 'com.android.volley:volley:1.2.1'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":vital-sign-engine")
implementation "androidx.camera:camera-core:1.1.0-beta02"
implementation "androidx.camera:camera-camera2:1.1.0-beta02"
implementation "androidx.camera:camera-lifecycle:1.1.0-beta02"
implementation "androidx.camera:camera-video:1.1.0-beta02"
implementation "androidx.camera:camera-view:1.1.0-beta02"
implementation "androidx.camera:camera-extensions:1.1.0-beta02"
implementation "androidx.exifinterface:exifinterface:1.3.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.5.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2"
}

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -1,234 +0,0 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

@ -1,89 +0,0 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -1,2 +0,0 @@
configurations.maybeCreate("default")
artifacts.add("default", file('vital-sign-engine-debug.aar'))

@ -1,3 +0,0 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ai.panoptic.vital_sign_camera">
</manifest>

@ -1,108 +0,0 @@
package ai.panoptic.vital_sign_camera
import ai.panoptic.wvs.camera.*
import ai.panoptic.wvs.engine.Converter
import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.View
import androidx.annotation.RequiresApi
import androidx.lifecycle.Lifecycle
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.platform.PlatformView
@RequiresApi(Build.VERSION_CODES.O)
class FlutterVitalSignCamera internal constructor(
context: Context,
messenger: BinaryMessenger,
id: Int,
props: Map<String, Any>,
lifecycle: Lifecycle
) : PlatformView, MethodChannel.MethodCallHandler, EventChannel.StreamHandler, VitalSignCameraEventHandler {
private val camera: VitalSignCamera
private val methodChannel: MethodChannel
private var eventSink: EventChannel.EventSink? = null
private val mainThread = Handler(Looper.getMainLooper())
override fun getView(): View {
return camera
}
init {
camera = VitalSignCamera(context, MLKitFaceDetector(), lifecycle, this)
methodChannel = MethodChannel(messenger, "ai.panoptic/channel/flutter_vital_sign_camera_$id")
methodChannel.setMethodCallHandler(this)
val eventChannel = EventChannel(messenger, "ai.panoptic/channel/flutter_vital_sign_camera_processed_frame_event_$id")
eventChannel.setStreamHandler(this)
camera.setProps(props)
}
override fun onMethodCall(methodCall: MethodCall, result: MethodChannel.Result) {
when (methodCall.method) {
"startScanning" -> {
camera.startStartScanning()
.thenAccept { result.success(null) }
.exceptionally {
result.error("-1", it.message, it.cause)
return@exceptionally null
}
}
"stopScanning" -> {
camera.stopScanning()
.thenAccept { result.success(null) }
.exceptionally {
result.error("-2", it.message, it.cause)
return@exceptionally null
}
}
"configure" -> {
val arguments = methodCall.arguments as? Map<String, Any>
arguments?.let {
camera.setProps(it)
}
}
else -> {
result.notImplemented()
}
}
}
override fun dispose() {
// camera.destroy()
}
override fun onVideoFrameProcessed(result: ai.panoptic.wvs.engine.ProcessFrameResult): kotlin.Unit {
// Already handled in onEvent.
// No need to handle here.
}
override fun onEvent(cameraView: VitalSignCamera, eventName: String, event: Map<String,Any>?) {
when(eventName) {
"videoFrameProcessed" -> {
eventSink?.let {
mainThread.post {
it.success(event)
}
}
}
}
}
override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
eventSink = events
}
override fun onCancel(arguments: Any?) {
eventSink = null
}
}

@ -1,165 +0,0 @@
package ai.panoptic.vital_sign_camera;
import static com.google.mlkit.vision.face.FaceContour.FACE;
import android.graphics.PointF;
import android.media.Image;
import android.util.ArraySet;
import com.google.android.gms.tasks.Task;
import com.google.mlkit.vision.common.InputImage;
import com.google.mlkit.vision.face.Face;
import com.google.mlkit.vision.face.FaceContour;
import com.google.mlkit.vision.face.FaceDetection;
import com.google.mlkit.vision.face.FaceDetector;
import com.google.mlkit.vision.face.FaceDetectorOptions;
import java.util.List;
import java.util.Set;
import ai.panoptic.wvs.engine.EyesOpenProbability;
import ai.panoptic.wvs.engine.FaceDetectorFeature;
import ai.panoptic.wvs.engine.HeadEulerAngle;
import ai.panoptic.wvs.engine.NormalizedFacebox;
import ai.panoptic.wvs.engine.VitalSignFaceDetector;
public class MLKitFaceDetector implements VitalSignFaceDetector {
ai.panoptic.wvs.engine.Face face = null;
FaceDetectorOptions options =
new FaceDetectorOptions.Builder()
.setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_FAST)
.setContourMode(FaceDetectorOptions.CONTOUR_MODE_NONE)
.setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
.setMinFaceSize(0.15f)
.build();
FaceDetector faceDetector = FaceDetection.getClient(options);
public ai.panoptic.wvs.engine.Face detectFace(Image mediaImage, int rotationDegrees) {
if (mediaImage == null) {
return null;
}
float width = mediaImage.getWidth();
float height = mediaImage.getHeight();
if (rotationDegrees == 270 || rotationDegrees == 90) {
width = mediaImage.getHeight();
height = mediaImage.getWidth();
}
final float _width = width;
final float _height = height;
InputImage image = InputImage.fromMediaImage(mediaImage, rotationDegrees);
Task<List<Face>> task = faceDetector.process(image);
task.addOnCompleteListener( result -> {
if (result.isCanceled()) {
return;
}
if (!result.isSuccessful()) {
return;
}
if (!result.isComplete()) {
return;
}
try {
List<Face> faces = result.getResult();
if (faces.isEmpty()) {
this.face = null;
return;
}
Face face = faces.get(0);
this.face = createFace(face, _width, _height);
} catch (Exception e) {
e.printStackTrace();
this.face = null;
}
});
return face;
}
static private ai.panoptic.wvs.engine.Face createFace(Face face, float _width, float _height) {
FaceContour contour = face.getContour(FACE);
NormalizedFacebox facebox = new NormalizedFacebox();
float minX = _width;
float minY = _height;
float maxX = 0;
float maxY = 0;
if (contour != null) {
for (PointF p : contour.getPoints()) {
if (p.x < minX) {
minX = p.x;
}
if (p.y < minY) {
minY = p.y;
}
if (p.x > maxX) {
maxX = p.x;
}
if (p.y > maxY) {
maxY = p.y;
}
}
} else {
minX = face.getBoundingBox().left;
minY = face.getBoundingBox().top;
maxX = face.getBoundingBox().right;
maxY = face.getBoundingBox().bottom;
}
facebox.xCenter = (minX + (maxX - minX) / 2.0f) / _width;
facebox.yCenter = (minY + (maxY - minY) / 2.0f) / _height;
facebox.width = (maxX - minX) / _width;
facebox.height = (maxY - minY) / _height;
ai.panoptic.wvs.engine.Face result = new ai.panoptic.wvs.engine.Face(facebox);
result.setEulerAngle(
new HeadEulerAngle(
face.getHeadEulerAngleX(),
face.getHeadEulerAngleY(),
face.getHeadEulerAngleY()
)
);
if (face.getLeftEyeOpenProbability() != null && face.getRightEyeOpenProbability() != null) {
result.setEyesOpenProbability(
new EyesOpenProbability(
face.getLeftEyeOpenProbability(),
face.getRightEyeOpenProbability()
)
);
}
return result;
}
@Override
public Set<FaceDetectorFeature> supportedFeatures() {
ArraySet<FaceDetectorFeature> features = new ArraySet<FaceDetectorFeature>();
features.add(FaceDetectorFeature.eyeOpenProbability);
features.add(FaceDetectorFeature.eulerAngle);
return features;
}
@Override
public NormalizedFacebox detect(Image mediaImage, int rotationDegrees) {
detectFace(mediaImage, rotationDegrees);
if (face == null) {
return null;
}
return face.getFacebox();
}
}

@ -1,145 +0,0 @@
package ai.panoptic.vital_sign_camera
import ai.panoptic.wvs.camera.availableCameraDevices
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.annotation.NonNull
import androidx.core.content.ContextCompat
import androidx.lifecycle.*
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/** VitalSignCameraPlugin */
class VitalSignCameraPlugin: FlutterPlugin, MethodCallHandler, ActivityAware,
RequestPermissionsResultListener {
companion object {
const val TAG = "VitalSignCameraPlugin"
fun parsePermissionStatus(status: Int): String {
return when (status) {
PackageManager.PERMISSION_DENIED -> "denied"
PackageManager.PERMISSION_GRANTED -> "authorized"
else -> "not-determined"
}
}
}
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel
private lateinit var pluginBinding: FlutterPlugin.FlutterPluginBinding
private lateinit var context: Context
private lateinit var activity: Activity
private lateinit var activityBinding:ActivityPluginBinding
private val coroutineScope = CoroutineScope(Dispatchers.Main)
private var requestCode = 1
private var permissionRequests = HashMap<Int, Result>()
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
Log.d("VitalSignCameraPlugin", "onAttachedToEngine")
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "vital_sign_camera_plugin")
channel.setMethodCallHandler(this)
pluginBinding = flutterPluginBinding
context = flutterPluginBinding.applicationContext
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
Log.d(TAG, "onAttachedToActivity")
val lifecycle: Lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding)
pluginBinding.platformViewRegistry.registerViewFactory(
"ai.panoptic/flutter_vital_sign_camera",
VitalSignCameraFactory(pluginBinding.binaryMessenger, lifecycle)
)
activity = binding.activity
activityBinding = binding
activityBinding.addRequestPermissionsResultListener(this)
}
override fun onDetachedFromActivityForConfigChanges() {}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {}
override fun onDetachedFromActivity() {
activityBinding.removeRequestPermissionsResultListener(this)
}
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"availableCameraDevices" -> {
coroutineScope.launch {
val devices = availableCameraDevices(context)
val returnValue = devices.map { it.map }
Log.d(TAG, "$returnValue")
result.success(returnValue)
}
}
"getCameraPermissionStatus" -> {
Log.d(TAG, "getCameraPermissionStatus")
val status =
parsePermissionStatus(
ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA))
result.success(status)
}
"requestCameraPermission" -> {
Log.d(TAG, "requestCameraPermission")
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// API 21 and below always grants permission on app install
result.success("authorized")
}
activity.requestPermissions(arrayOf(Manifest.permission.CAMERA), requestCode)
permissionRequests[requestCode] = result
requestCode += 1
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
): Boolean {
permissionRequests[requestCode]?.let {
val permissionStatus = if (grantResults.isNotEmpty()) grantResults[0] else PackageManager.PERMISSION_DENIED
it.success(parsePermissionStatus(permissionStatus))
permissionRequests.remove(requestCode)
return true
}
return false
}
}

@ -1,218 +0,0 @@
//
// MLKitFaceDetector.swift
// VitalSignEngineCore
//
// Created by Eddie Lau on 24/8/2022.
//
import Foundation
import MLKitFaceDetection
import MLKitVision
import VitalSignEngineCore
public class MLKitFaceDetector : VitalSignFaceDetector {
public typealias Face = MLKitFace
public let supportedFeatures: Set<VitalSignEngineCore.FaceDetectorFeature>
= [.eyesOpenProbability, .eularAngle]
public init() {
}
public let maxDetectionHeight:CGFloat = 240
let fps = Fps(name: "MLKitFaceDetector")
lazy var faceDetector:FaceDetector = {
let option = FaceDetectorOptions()
option.contourMode = .all
option.classificationMode = .all
option.landmarkMode = .none
option.performanceMode = .fast
return FaceDetector.faceDetector(options: option)
}()
var face:Face? {
didSet {
fps.tick()
}
}
public var frameRate: Double? { fps.lastReportedAverage }
public var maxConcurrency = 2
var jobCount = 0
public func detect(from frame: UIImage) -> Face? {
guard jobCount < maxConcurrency else {
return face
}
jobCount += 1
DispatchQueue.global().async {
let scaledFrame = self.scaled(videoFrame: frame)
let frameSize = scaledFrame.size
let image = VisionImage(image: scaledFrame)
image.orientation = image.orientation
DispatchQueue.main.async {
self.faceDetector.process(image) { faces, error in
guard let face = faces?.first else {
self.face = nil
self.jobCount -= 1
return
}
self.face = MLKitFace(face: face, frameSize: frameSize)
self.jobCount -= 1
}
}
}
return face
}
func scaled(videoFrame frame:UIImage) -> UIImage {
var scale = CGFloat(1.0)
if frame.size.height > maxDetectionHeight {
scale = maxDetectionHeight / frame.size.height
}
let scaledScale = CGSize(width:frame.size.width * scale, height:frame.size.height * scale)
return frame.resizedImage(size: scaledScale)!
}
}
public struct MLKitFaceLandmarks: FaceLandmarks {
public typealias ContourType = FaceContour
let mlkitFace:MLKitFaceDetection.Face
public let videoFrameSize: CGSize
init(mlkitFace: MLKitFaceDetection.Face, videoFrameSize: CGSize) {
self.mlkitFace = mlkitFace
self.videoFrameSize = videoFrameSize
}
public var faceOval: FaceContour? { mlkitFace.contour(ofType: .face) }
public func contour(of type: VitalSignEngineCore.FaceLandmarkType) -> FaceContour? {
guard let contourType = type.asContourType else { return nil }
return mlkitFace.contour(ofType: contourType)
}
}
public class MLKitFace : FaceProtocol {
public typealias ContourType = FaceContour
let mlkitFace:MLKitFaceDetection.Face
public let faceBox: NormalizedFaceBox
public let faceLandmarks: MLKitFaceLandmarks
public let eulerAngle: (x: CGFloat, y: CGFloat, z: CGFloat)?
public let eyesOpenProbability: (leftEye:CGFloat, rightEye:CGFloat)?
init?(face:MLKitFaceDetection.Face, frameSize:CGSize) {
self.mlkitFace = face
self.faceLandmarks = MLKitFaceLandmarks(mlkitFace: face, videoFrameSize: frameSize)
guard let faceContour = face.contour(ofType: FaceContourType.face) else {
return nil
}
let eyesOpenPropbability: (leftEye:CGFloat, rightEye:CGFloat)?
if face.hasLeftEyeOpenProbability && face.hasRightEyeOpenProbability {
eyesOpenPropbability = (face.leftEyeOpenProbability, face.rightEyeOpenProbability)
} else {
eyesOpenPropbability = nil
}
self.eyesOpenProbability = eyesOpenPropbability
let eulerAngle: (x:CGFloat, y:CGFloat, z:CGFloat)?
if face.hasHeadEulerAngleX && face.hasHeadEulerAngleY && face.hasHeadEulerAngleZ {
eulerAngle = (face.headEulerAngleX, face.headEulerAngleY, face.headEulerAngleZ)
} else {
eulerAngle = nil
}
self.eulerAngle = eulerAngle
self.faceBox = faceContour.toFacebox(frameSize: frameSize)
}
}
fileprivate extension MLKitFaceDetection.FaceContour {
func toFacebox(frameSize:CGSize) -> NormalizedFaceBox {
var minX = CGFloat.greatestFiniteMagnitude
var minY = CGFloat.greatestFiniteMagnitude
var maxX = -CGFloat.greatestFiniteMagnitude
var maxY = -CGFloat.greatestFiniteMagnitude
points.forEach { point in
minX = min(minX, point.x)
minY = min(minY, point.y)
maxX = max(maxX, point.x)
maxY = max(maxY, point.y)
}
return NormalizedFaceBox(
xCenter: ((maxX - minX)/2 + minX) / frameSize.width,
yCenter: ((maxY - minY)/2 + minY) / frameSize.height,
width: (maxX - minX) / frameSize.width,
height: (maxY - minY) / frameSize.height
)
}
}
fileprivate extension UIImage {
func resizedImage(size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
defer { UIGraphicsEndImageContext() }
draw(in: CGRect(origin: .zero, size: size))
let image = UIGraphicsGetImageFromCurrentImageContext()
return image?.data.flatMap(UIImage.init) // This line is copied from MLKit, Not sure why is needed
}
private var data: Data? {
#if swift(>=4.2)
return pngData() ?? jpegData(compressionQuality: Constant.jpegCompressionQuality)
#else
return pngData() ?? jpegData(compressionQuality: Constant.jpegCompressionQuality)
#endif // swift(>=4.2)
}
private enum Constant {
static let jpegCompressionQuality: CGFloat = 0.8
}
}
extension VisionPoint : FaceContourPoint {
}
extension FaceContour : Contour {
}
extension VitalSignEngineCore.FaceLandmarkType {
var asContourType:MLKitFaceDetection.FaceContourType? {
switch self {
case .faceOval: return .face
case .leftEyebrowTop: return .leftEyebrowTop
case .leftEyebrowBottom: return .leftEyebrowBottom
case .rightEyebrowTop: return .rightEyebrowTop
case .rightEyebrowBottom: return .rightEyebrowBottom
case .leftEye: return .leftEye
case .rightEye: return .rightEye
case .upperLipTop: return .upperLipTop
case .upperLipBottom: return .upperLipBottom
case .lowerLipTop: return .lowerLipTop
case .lowerLipBottom: return .lowerLipBottom
case .noseBridge: return .noseBridge
case .noseBottom: return .noseBottom
case .leftCheek: return .leftCheek
case .rightCheek: return .rightCheek
@unknown default: return nil
}
}
}

@ -1,91 +0,0 @@
import Flutter
import UIKit
import VitalSignEngineCore
public class SwiftVitalSignCameraPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "vital_sign_camera_plugin", binaryMessenger: registrar.messenger())
let instance = SwiftVitalSignCameraPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
registrar.register(VitalSignCameraFactory(messenger: registrar.messenger()), withId: "ai.panoptic/flutter_vital_sign_camera")
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
if call.method == "availableCameraDevices" {
let devices = VitalSignCamera.availableCameraDevices()
result(devices.map({ $0.flutterCompatibleDict }))
}
if call.method == "requestCameraPermission" {
VitalSignCamera.requestCameraPermission().done { status in
result(status.rawValue)
}.catch { error in
result(FlutterError(code: "\(error.code)", message: error.message, details: nil))
}
}
if call.method == "getCameraPermissionStatus" {
let status = VitalSignCamera.getCameraPermissionStatus()
result(status.rawValue)
}
}
}
fileprivate extension CameraDevice {
var flutterCompatibleDict:[String:Any] {
[
"id": id,
"devices": devices.map { $0.rawValue },
"position": position.rawValue,
"name": name,
"hasFlash": NSNumber(value: hasFlash),
"hasTorch": NSNumber(value: hasTorch),
"minZoom": NSNumber(value: Double(minZoom)),
"neutralZoom": NSNumber(value: Double(neutralZoom)),
"maxZoom": NSNumber(value: Double(maxZoom)),
"isMultiCam": NSNumber(value: isMultiCam),
"supportsParallelVideoProcessing": NSNumber(value: supportsParallelVideoProcessing),
"supportsDepthCapture": NSNumber(value: supportsDepthCapture),
"supportsRawCapture": NSNumber(value: supportsRawCapture),
"supportsLowLightBoost": NSNumber(value: supportsLowLightBoost),
"supportsFocus": NSNumber(value: supportsFocus),
"formats": formats.map { format -> [String: Any] in
format.flutterCompatibleDict
},
]
}
}
fileprivate extension CameraCaptureFormat {
var flutterCompatibleDict:[String:Any] {
var dict:[String:Any] = [
"videoStabilizationModes": videoStabilizationModes.map { $0.rawValue },
"autoFocusSystem": autoFocusSystem.rawValue,
"photoHeight": NSNumber(value: Double(photoHeight)),
"photoWidth": NSNumber(value: Double(photoWidth)),
"videoHeight": NSNumber(value: Double(videoHeight)),
"videoWidth": NSNumber(value: Double(videoWidth)),
"maxISO": NSNumber(value: Int(maxISO)),
"minISO": NSNumber(value: Int(minISO)),
"fieldOfView": NSNumber(value: Double(fieldOfView)),
"maxZoom": NSNumber(value: Double(maxZoom)),
"colorSpaces": colorSpaces.map { $0.rawValue },
"supportsVideoHDR": NSNumber(value: supportsVideoHDR),
"supportsPhotoHDR": NSNumber(value: supportsPhotoHDR),
"frameRateRanges": frameRateRanges.map {
[
"minFrameRate": NSNumber(value: Int($0.minFrameRate)),
"maxFrameRate": NSNumber(value: Int($0.maxFrameRate)),
]
},
"pixelFormat": pixelFormat.rawValue,
]
if let isHighestPhotoQualitySupported = isHighestPhotoQualitySupported {
dict["isHighestPhotoQualitySupported"] = isHighestPhotoQualitySupported
}
return dict
}
}

@ -1,37 +0,0 @@
//
// VitalSignCameraFactory.swift
// vital_sign_camera
//
// Created by Eddie Lau on 24/1/2023.
//
import Foundation
import Foundation
import Flutter
import UIKit
class VitalSignCameraFactory: NSObject, FlutterPlatformViewFactory {
private var messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(
withFrame frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?
) -> FlutterPlatformView {
return FlutterVitalSignCamera(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger)
}
func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
FlutterStandardMessageCodec.sharedInstance()
}
}

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

Loading…
Cancel
Save