diff --git a/android/app/build.gradle b/android/app/build.gradle
index 26a2484d..96428f49 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -54,6 +54,11 @@ android {
signingConfig signingConfigs.debug
}
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
}
flutter {
@@ -65,6 +70,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
@@ -74,9 +80,10 @@ dependencies {
//permissions
implementation 'pub.devrel:easypermissions:0.4.0'
//retrofit
- implementation 'com.squareup.retrofit2:retrofit:2.6.2'
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
- implementation 'com.squareup.okhttp3:logging-interceptor:3.14.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
}
apply plugin: 'com.google.gms.google-services'
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index c656ebbf..bf0d3766 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -9,18 +9,24 @@
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here.
-->
-
-
-
+
+
+
+
+
+
+
+
+
+
-
("kApiKey")
- val sessionId = call.argument("kSessionId")
- val token = call.argument("kToken")
- val appLang = call.argument("appLang")
- val baseUrl = call.argument("baseUrl")
+ when (call.method) {
+ "openVideoCall" -> {
+ val apiKey = call.argument("kApiKey")
+ val sessionId = call.argument("kSessionId")
+ val token = call.argument("kToken")
+ val appLang = call.argument("appLang")
+ val baseUrl = call.argument("baseUrl")
+
+ // Session Status model
+ val VC_ID = call.argument("VC_ID")
+ val tokenID = call.argument("TokenID")
+ val generalId = call.argument("generalId")
+ val doctorId = call.argument("DoctorId")
+ val patientName = call.argument("patientName")
- // Session Status model
- val VC_ID = call.argument("VC_ID")
- val tokenID = call.argument("TokenID")
- val generalId = call.argument("generalId")
- val doctorId = call.argument("DoctorId")
+ val sessionStatusModel = GetSessionStatusModel(VC_ID, tokenID, generalId, doctorId, patientName)
- val sessionStatusModel = GetSessionStatusModel(VC_ID, tokenID, generalId, doctorId)
+ openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel)
- openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel)
+ }
+ "closeVideoCall" -> {
+ dialogFragment?.onCallClicked()
+ }
+ "onCallConnected" -> {
- } else {
- result.notImplemented()
+ }
+ else -> {
+ result.notImplemented()
+ }
}
}
private fun openVideoCall(apiKey: String?, sessionId: String?, token: String?, appLang: String?, baseUrl: String?, sessionStatusModel: GetSessionStatusModel) {
- // val videoCallActivity = VideoCallActivity()
+ if (dialogFragment == null) {
+ val arguments = Bundle()
+ arguments.putString("apiKey", apiKey)
+ arguments.putString("sessionId", sessionId)
+ arguments.putString("token", token)
+ arguments.putString("appLang", appLang)
+ arguments.putString("baseUrl", baseUrl)
+ arguments.putParcelable("sessionStatusModel", sessionStatusModel)
+
+ val transaction = supportFragmentManager.beginTransaction()
+ dialogFragment = VideoCallFragment.newInstance(arguments)
+ dialogFragment?.let {
+ it.setCallListener(this)
+ it.isCancelable = true
+ if (it.isAdded){
+ it.dismiss()
+ }else {
+ it.show(transaction, "dialog")
+ }
- val intent = Intent(this, VideoCallActivity::class.java)
- intent.putExtra("apiKey", apiKey)
- intent.putExtra("sessionId", sessionId)
- intent.putExtra("token", token)
- intent.putExtra("appLang", appLang)
- intent.putExtra("baseUrl", baseUrl)
- intent.putExtra("sessionStatusModel", sessionStatusModel)
- startActivityForResult(intent, LAUNCH_VIDEO)
+ }
+ } else if (!dialogFragment!!.isVisible) {
+ val transaction = supportFragmentManager.beginTransaction()
+ dialogFragment!!.show(transaction, "dialog")
+ }
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- super.onActivityResult(requestCode, resultCode, data)
- var asd = "";
- if (requestCode == LAUNCH_VIDEO) {
- if (resultCode == Activity.RESULT_OK) {
- val result : SessionStatusModel? = data?.getParcelableExtra("sessionStatusNotRespond")
- val callResponse : HashMap = HashMap()
+ /* override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ var asd = "";
+ if (requestCode == LAUNCH_VIDEO) {
+ if (resultCode == Activity.RESULT_OK) {
+ val result : SessionStatusModel? = data?.getParcelableExtra("sessionStatusNotRespond")
+ val callResponse : HashMap = HashMap()
+
+ val sessionStatus : HashMap = HashMap()
+ val gson = GsonBuilder().serializeNulls().create()
- val sessionStatus : HashMap = HashMap()
- val gson = GsonBuilder().serializeNulls().create()
+ callResponse["callResponse"] = "CallNotRespond"
+ val jsonRes = gson.toJson(result)
+ callResponse["sessionStatus"] = jsonRes
- callResponse["callResponse"] = "CallNotRespond"
- val jsonRes = gson.toJson(result)
- callResponse["sessionStatus"] = jsonRes
+ this.result?.success(callResponse)
+ }
+ if (resultCode == Activity.RESULT_CANCELED) {
+ val callResponse : HashMap = HashMap()
+ callResponse["callResponse"] = "CallEnd"
+ result?.success(callResponse)
+ }
+ }
+ }*/
+
+ override fun onCallFinished(resultCode: Int, intent: Intent?) {
+ dialogFragment = null
+
+ if (resultCode == Activity.RESULT_OK) {
+ val result: SessionStatusModel? = intent?.getParcelableExtra("sessionStatusNotRespond")
+ val callResponse: HashMap = HashMap()
+
+ val sessionStatus: HashMap = HashMap()
+ val gson = GsonBuilder().serializeNulls().create()
+
+ callResponse["callResponse"] = "CallNotRespond"
+ val jsonRes = gson.toJson(result)
+ callResponse["sessionStatus"] = jsonRes
+
+ try {
this.result?.success(callResponse)
+ } catch (e : Exception){
+ Log.e("onVideoCallFinished", "${e.message}.")
}
- if (resultCode == Activity.RESULT_CANCELED) {
- val callResponse : HashMap = HashMap()
- callResponse["callResponse"] = "CallEnd"
-
+ } else if (resultCode == Activity.RESULT_CANCELED) {
+ val callResponse: HashMap = HashMap()
+ callResponse["callResponse"] = "CallEnd"
+ try {
result?.success(callResponse)
+ } catch (e : Exception){
+ Log.e("onVideoCallFinished", "${e.message}.")
}
}
}
+ override fun errorHandle(message: String) {
+ dialogFragment = null
+// Toast.makeText(this, message, Toast.LENGTH_LONG).show()
+ }
+
+ override fun minimizeVideoEvent(isMinimize: Boolean) {
+ if (isMinimize)
+ methodChannel.invokeMethod("onCallConnected", null)
+ else
+ methodChannel.invokeMethod("onCallDisconnected", null)
+ }
+
+ override fun onBackPressed() {
+ super.onBackPressed()
+ }
}
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java b/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java
index d41aa146..60350539 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java
@@ -20,15 +20,19 @@ public class GetSessionStatusModel implements Parcelable {
@SerializedName("DoctorId")
@Expose
private Integer doctorId;
+ @SerializedName("PatientName")
+ @Expose
+ private String patientName;
public GetSessionStatusModel() {
}
- public GetSessionStatusModel(Integer vCID, String tokenID, String generalid, Integer doctorId) {
+ public GetSessionStatusModel(Integer vCID, String tokenID, String generalid, Integer doctorId, String patientName) {
this.vCID = vCID;
this.tokenID = tokenID;
this.generalid = generalid;
this.doctorId = doctorId;
+ this.patientName = patientName;
}
protected GetSessionStatusModel(Parcel in) {
@@ -44,6 +48,7 @@ public class GetSessionStatusModel implements Parcelable {
} else {
doctorId = in.readInt();
}
+ patientName = in.readString();
}
public static final Creator CREATOR = new Creator() {
@@ -90,6 +95,16 @@ public class GetSessionStatusModel implements Parcelable {
this.doctorId = doctorId;
}
+ public String getPatientName() {
+ if (patientName == null)
+ patientName = "-";
+ return patientName;
+ }
+
+ public void setPatientName(String patientName) {
+ this.patientName = patientName;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -111,5 +126,6 @@ public class GetSessionStatusModel implements Parcelable {
dest.writeByte((byte) 1);
dest.writeInt(doctorId);
}
+ dest.writeString(patientName);
}
}
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallActivity.java b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallActivity.java
deleted file mode 100644
index 1c907089..00000000
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallActivity.java
+++ /dev/null
@@ -1,442 +0,0 @@
-package com.hmg.hmgDr.ui;
-
-import androidx.annotation.NonNull;
-import androidx.appcompat.app.AppCompatActivity;
-
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Intent;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.os.CountDownTimer;
-import android.os.Handler;
-import android.util.Log;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
-import com.hmg.hmgDr.Model.GetSessionStatusModel;
-import com.hmg.hmgDr.Model.SessionStatusModel;
-import com.hmg.hmgDr.R;
-import com.opentok.android.Session;
-import com.opentok.android.Stream;
-import com.opentok.android.Publisher;
-import com.opentok.android.PublisherKit;
-import com.opentok.android.Subscriber;
-import com.opentok.android.BaseVideoRenderer;
-import com.opentok.android.OpentokError;
-import com.opentok.android.SubscriberKit;
-
-import java.util.List;
-import java.util.Objects;
-
-import pub.devrel.easypermissions.AfterPermissionGranted;
-import pub.devrel.easypermissions.AppSettingsDialog;
-import pub.devrel.easypermissions.EasyPermissions;
-
-public class VideoCallActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,
- Session.SessionListener,
- Publisher.PublisherListener,
- Subscriber.VideoListener, VideoCallContract.VideoCallView {
-
- private static final String TAG = VideoCallActivity.class.getSimpleName();
-
- VideoCallContract.VideoCallPresenter videoCallPresenter;
-
- private static final int RC_SETTINGS_SCREEN_PERM = 123;
- private static final int RC_VIDEO_APP_PERM = 124;
-
-
- private Session mSession;
- private Publisher mPublisher;
- private Subscriber mSubscriber;
-
- private Handler mVolHandler, mConnectedHandler;
- private Runnable mVolRunnable, mConnectedRunnable;
-
- private FrameLayout mPublisherViewContainer;
- private RelativeLayout mSubscriberViewContainer;
- private RelativeLayout controlPanel;
-
- private String apiKey;
- private String sessionId;
- private String token;
- private String appLang;
- private String baseUrl;
-
- private boolean isSwitchCameraClicked;
- private boolean isCameraClicked;
- private boolean isSpeckerClicked;
- private boolean isMicClicked;
-
- private ImageView mCallBtn;
- private ImageView mCameraBtn;
- private ImageView mSwitchCameraBtn;
- private ImageView mspeckerBtn;
- private ImageView mMicBtn;
-
- private ProgressBar progressBar;
- private CountDownTimer countDownTimer;
- private TextView progressBarTextView;
- private RelativeLayout progressBarLayout;
-
- private boolean isConnected = false;
-
- private GetSessionStatusModel sessionStatusModel;
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- setTheme(R.style.AppTheme);
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_video_call);
- Objects.requireNonNull(getSupportActionBar()).hide();
- initUI();
- requestPermissions();
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- if (mSession == null) {
- return;
- }
- mSession.onPause();
-
- if (isFinishing()) {
- disconnectSession();
- }
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- if (mSession == null) {
- return;
- }
- mSession.onResume();
- }
-
- @Override
- protected void onDestroy() {
- disconnectSession();
-
- super.onDestroy();
- }
-
- @SuppressLint("ClickableViewAccessibility")
- private void initUI() {
- mPublisherViewContainer = (FrameLayout) findViewById(R.id.local_video_view_container);
- mSubscriberViewContainer = (RelativeLayout) findViewById(R.id.remote_video_view_container);
-
- apiKey = getIntent().getStringExtra("apiKey");
- sessionId = getIntent().getStringExtra("sessionId");
- token = getIntent().getStringExtra("token");
- appLang = getIntent().getStringExtra("appLang");
- baseUrl = getIntent().getStringExtra("baseUrl");
- sessionStatusModel = getIntent().getParcelableExtra("sessionStatusModel");
-
- controlPanel = findViewById(R.id.control_panel);
-
- videoCallPresenter = new VideoCallPresenterImpl(this, baseUrl);
-
-
- mCallBtn = findViewById(R.id.btn_call);
- mCameraBtn = findViewById(R.id.btn_camera);
- mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);
- mspeckerBtn = findViewById(R.id.btn_specker);
- mMicBtn = findViewById(R.id.btn_mic);
-
- // progressBarLayout=findViewById(R.id.progressBar);
- // progressBar=findViewById(R.id.progress_bar);
-// progressBarTextView=findViewById(R.id.progress_bar_text);
-// progressBar.setVisibility(View.GONE);
-
- hiddenButtons();
-
- checkClientConnected();
-
- mSubscriberViewContainer.setOnTouchListener((v, event) -> {
- controlPanel.setVisibility(View.VISIBLE);
- mVolHandler.removeCallbacks(mVolRunnable);
- mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
- return true;
- });
-
- if (appLang.equals("ar")) {
- progressBarLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
- }
-
- }
-
- private void checkClientConnected() {
- mConnectedHandler = new Handler();
- mConnectedRunnable = () -> {
- if (!isConnected) {
- videoCallPresenter.callClintConnected(sessionStatusModel);
- }
- };
- mConnectedHandler.postDelayed(mConnectedRunnable, 30 * 1000);
-
- }
-
- private void hiddenButtons() {
- mVolHandler = new Handler();
- mVolRunnable = new Runnable() {
- public void run() {
- controlPanel.setVisibility(View.GONE);
- }
- };
- mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-
- EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
- }
-
- @Override
- public void onPermissionsGranted(int requestCode, List perms) {
- Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
- }
-
- @Override
- public void onPermissionsDenied(int requestCode, List perms) {
- Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
-
- if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
- new AppSettingsDialog.Builder(this)
- .setTitle(getString(R.string.title_settings_dialog))
- .setRationale(getString(R.string.rationale_ask_again))
- .setPositiveButton(getString(R.string.setting))
- .setNegativeButton(getString(R.string.cancel))
- .setRequestCode(RC_SETTINGS_SCREEN_PERM)
- .build()
- .show();
- }
- }
-
- @AfterPermissionGranted(RC_VIDEO_APP_PERM)
- private void requestPermissions() {
- String[] perms = {Manifest.permission.INTERNET, Manifest.permission.CAMERA,};
- if (EasyPermissions.hasPermissions(this, perms)) {
- try {
- mSession = new Session.Builder(this, apiKey, sessionId).build();
- mSession.setSessionListener(this);
- mSession.connect(token);
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, perms);
- }
- }
-
- @Override
- public void onConnected(Session session) {
- Log.i(TAG, "Session Connected");
-
- mPublisher = new Publisher.Builder(this).build();
- mPublisher.setPublisherListener(this);
-
- mPublisherViewContainer.addView(mPublisher.getView());
-
- if (mPublisher.getView() instanceof GLSurfaceView) {
- ((GLSurfaceView) mPublisher.getView()).setZOrderOnTop(true);
- }
-
- mSession.publish(mPublisher);
- }
-
- @Override
- public void onDisconnected(Session session) {
- Log.d(TAG, "onDisconnected: disconnected from session " + session.getSessionId());
-
- mSession = null;
- }
-
- @Override
- public void onError(Session session, OpentokError opentokError) {
- Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in session " + session.getSessionId());
-
- Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
- finish();
- }
-
- @Override
- public void onStreamReceived(Session session, Stream stream) {
- Log.d(TAG, "onStreamReceived: New stream " + stream.getStreamId() + " in session " + session.getSessionId());
- if (mSubscriber != null) {
- isConnected = true;
- return;
- }
- isConnected = true;
- subscribeToStream(stream);
- videoCallPresenter.callChangeCallStatus(new ChangeCallStatusRequestModel(3,sessionStatusModel.getDoctorId(), sessionStatusModel.getGeneralid(),token,sessionStatusModel.getVCID()));
- }
-
- @Override
- public void onStreamDropped(Session session, Stream stream) {
- Log.d(TAG, "onStreamDropped: Stream " + stream.getStreamId() + " dropped from session " + session.getSessionId());
-
- if (mSubscriber == null) {
- return;
- }
-
- if (mSubscriber.getStream().equals(stream)) {
- mSubscriberViewContainer.removeView(mSubscriber.getView());
- mSubscriber.destroy();
- mSubscriber = null;
- }
- disconnectSession();
- }
-
- @Override
- public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
- Log.d(TAG, "onStreamCreated: Own stream " + stream.getStreamId() + " created");
- }
-
- @Override
- public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
- Log.d(TAG, "onStreamDestroyed: Own stream " + stream.getStreamId() + " destroyed");
- }
-
- @Override
- public void onError(PublisherKit publisherKit, OpentokError opentokError) {
- Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in publisher");
-
- Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
- finish();
- }
-
- @Override
- public void onVideoDataReceived(SubscriberKit subscriberKit) {
- mSubscriber.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL);
- mSubscriberViewContainer.addView(mSubscriber.getView());
- }
-
- @Override
- public void onVideoDisabled(SubscriberKit subscriberKit, String s) {
-
- }
-
- @Override
- public void onVideoEnabled(SubscriberKit subscriberKit, String s) {
-
- }
-
- @Override
- public void onVideoDisableWarning(SubscriberKit subscriberKit) {
-
- }
-
- @Override
- public void onVideoDisableWarningLifted(SubscriberKit subscriberKit) {
-
- }
-
- private void subscribeToStream(Stream stream) {
- mSubscriber = new Subscriber.Builder(VideoCallActivity.this, stream).build();
- mSubscriber.setVideoListener(this);
- mSession.subscribe(mSubscriber);
- }
-
- private void disconnectSession() {
- if (mSession == null) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- return;
- }
-
- if (mSubscriber != null) {
- mSubscriberViewContainer.removeView(mSubscriber.getView());
- mSession.unsubscribe(mSubscriber);
- mSubscriber.destroy();
- mSubscriber = null;
- }
-
- if (mPublisher != null) {
- mPublisherViewContainer.removeView(mPublisher.getView());
- mSession.unpublish(mPublisher);
- mPublisher.destroy();
- mPublisher = null;
- }
- mSession.disconnect();
- if (countDownTimer != null) {
- countDownTimer.cancel();
- }
- videoCallPresenter.callChangeCallStatus(new ChangeCallStatusRequestModel(16,sessionStatusModel.getDoctorId(), sessionStatusModel.getGeneralid(),token,sessionStatusModel.getVCID()));
- finish();
- }
-
- public void onSwitchCameraClicked(View view) {
- if (mPublisher != null) {
- isSwitchCameraClicked = !isSwitchCameraClicked;
- mPublisher.cycleCamera();
- int res = isSwitchCameraClicked ? R.drawable.flip_disapled : R.drawable.flip_enabled;
- mSwitchCameraBtn.setImageResource(res);
- }
- }
-
- public void onCameraClicked(View view) {
- if (mPublisher != null) {
- isCameraClicked = !isCameraClicked;
- mPublisher.setPublishVideo(!isCameraClicked);
- int res = isCameraClicked ? R.drawable.video_disanabled : R.drawable.video_enabled;
- mCameraBtn.setImageResource(res);
- }
- }
-
- public void onSpeckerClicked(View view) {
- if (mSubscriber != null) {
- isSpeckerClicked = !isSpeckerClicked;
- mSubscriber.setSubscribeToAudio(!isSpeckerClicked);
- int res = isSpeckerClicked ? R.drawable.audio_disabled : R.drawable.audio_enabled;
- mspeckerBtn.setImageResource(res);
- }
- }
-
- public void onMicClicked(View view) {
-
- if (mPublisher != null) {
- isMicClicked = !isMicClicked;
- mPublisher.setPublishAudio(!isMicClicked);
- int res = isMicClicked ? R.drawable.mic_disabled : R.drawable.mic_enabled;
- mMicBtn.setImageResource(res);
- }
- }
-
- public void onCallClicked(View view) {
- disconnectSession();
- }
-
- @Override
- public void onCallSuccessful(SessionStatusModel sessionStatusModel) {
- if (sessionStatusModel.getSessionStatus() == 2 || sessionStatusModel.getSessionStatus() == 3) {
- Intent returnIntent = new Intent();
- returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel);
- setResult(Activity.RESULT_OK, returnIntent);
- finish();
- }
- }
-
- @Override
- public void onCallChangeCallStatusSuccessful(SessionStatusModel sessionStatusModel) {
-
- }
-
- @Override
- public void onFailure() {
-
- }
-}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallResponseListener.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallResponseListener.kt
new file mode 100644
index 00000000..204568a4
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallResponseListener.kt
@@ -0,0 +1,14 @@
+package com.hmg.hmgDr.ui
+
+import android.content.Intent
+
+interface VideoCallResponseListener {
+
+ fun onCallFinished(resultCode : Int, intent: Intent? = null)
+
+ fun errorHandle(message: String)
+
+ fun minimizeVideoEvent(isMinimize : Boolean)
+
+ fun onBackHandle(){}
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt
new file mode 100644
index 00000000..35e28b23
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt
@@ -0,0 +1,893 @@
+package com.hmg.hmgDr.ui.fragment
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.app.Activity
+import android.app.Dialog
+import android.content.Context
+import android.content.Intent
+import android.graphics.Color
+import android.graphics.Point
+import android.graphics.drawable.ColorDrawable
+import android.opengl.GLSurfaceView
+import android.os.*
+import android.util.Log
+import android.view.*
+import android.widget.*
+import androidx.annotation.Nullable
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.content.ContextCompat
+import androidx.core.view.GestureDetectorCompat
+import androidx.fragment.app.DialogFragment
+import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel
+import com.hmg.hmgDr.Model.GetSessionStatusModel
+import com.hmg.hmgDr.Model.SessionStatusModel
+import com.hmg.hmgDr.R
+import com.hmg.hmgDr.ui.VideoCallContract.VideoCallPresenter
+import com.hmg.hmgDr.ui.VideoCallContract.VideoCallView
+import com.hmg.hmgDr.ui.VideoCallPresenterImpl
+import com.hmg.hmgDr.ui.VideoCallResponseListener
+import com.hmg.hmgDr.util.DynamicVideoRenderer
+import com.hmg.hmgDr.util.ThumbnailCircleVideoRenderer
+import com.opentok.android.*
+import com.opentok.android.PublisherKit.PublisherListener
+import pub.devrel.easypermissions.AfterPermissionGranted
+import pub.devrel.easypermissions.AppSettingsDialog
+import pub.devrel.easypermissions.EasyPermissions
+import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks
+import kotlin.math.ceil
+
+
+class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.SessionListener, PublisherListener,
+ SubscriberKit.VideoListener, VideoCallView {
+
+ private var isFullScreen: Boolean = true
+ private var isCircle: Boolean = false
+ private var x_init_cord = 0
+ private var y_init_cord: Int = 0
+ private var x_init_margin: Int = 0
+ private var y_init_margin: Int = 0
+ private val szWindow: Point = Point()
+ private lateinit var mWindowManager: WindowManager
+ private var isLeft = true
+
+ private lateinit var videoCallPresenter: VideoCallPresenter
+
+ private var mSession: Session? = null
+ private var mPublisher: Publisher? = null
+ private var mSubscriber: Subscriber? = null
+
+ private var mVolHandler: Handler? = null
+ private var mConnectedHandler: Handler? = null
+ private var mVolRunnable: Runnable? = null
+ private var mConnectedRunnable: Runnable? = null
+
+ private lateinit var thumbnail_container: FrameLayout
+ private lateinit var mPublisherViewContainer: FrameLayout
+ private lateinit var mPublisherViewIcon: View
+ private lateinit var mSubscriberViewContainer: FrameLayout
+ private lateinit var mSubscriberViewIcon: ImageView
+ private lateinit var controlPanel: ConstraintLayout
+
+ private var apiKey: String? = null
+ private var sessionId: String? = null
+ private var token: String? = null
+ private var appLang: String? = null
+ private var baseUrl: String? = null
+
+ private var isSwitchCameraClicked = false
+ private var isCameraClicked = false
+ private var isSpeckerClicked = false
+ private var isMicClicked = false
+
+ private lateinit var parentView: View
+ private lateinit var videoCallContainer: ConstraintLayout
+ private lateinit var layoutName: RelativeLayout
+ private lateinit var layoutMini: RelativeLayout
+ private lateinit var icMini: ImageButton
+ private lateinit var mCallBtn: ImageView
+ private lateinit var btnMinimize: ImageView
+ private lateinit var mCameraBtn: ImageView
+ private lateinit var mSwitchCameraBtn: ImageView
+ private lateinit var mspeckerBtn: ImageView
+ private lateinit var mMicBtn: ImageView
+
+ private lateinit var patientName: TextView
+ private lateinit var cmTimer: Chronometer
+ private var elapsedTime: Long = 0
+ private var resume = false
+
+ private val progressBar: ProgressBar? = null
+ private val countDownTimer: CountDownTimer? = null
+ private val progressBarTextView: TextView? = null
+ private val progressBarLayout: RelativeLayout? = null
+
+ private var isConnected = false
+
+ private var sessionStatusModel: GetSessionStatusModel? = null
+ private var videoCallResponseListener: VideoCallResponseListener? = null
+ private lateinit var mDetector: GestureDetectorCompat
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ requireActivity().setTheme(R.style.AppTheme)
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ dialog?.window?.setLayout(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ )
+ }
+
+ override fun getTheme(): Int {
+ return R.style.dialogTheme
+ }
+
+ override fun onCreateDialog(@Nullable savedInstanceState: Bundle?): Dialog {
+ val dialog: Dialog = super.onCreateDialog(savedInstanceState)
+
+ // Add back button listener
+ // Add back button listener
+ dialog.setOnKeyListener { _, keyCode, keyEvent ->
+ // getAction to make sure this doesn't double fire
+ if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) {
+ videoCallResponseListener?.onBackHandle()
+ false // Capture onKey
+ } else true
+ // Don't capture
+ }
+
+ return dialog
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ // This is done in a post() since the dialog must be drawn before locating.
+ requireView().post {
+ val dialogWindow = dialog!!.window
+
+ if (dialog != null && dialogWindow != null) {
+ dialogWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
+ }
+
+ // Make the dialog possible to be outside touch
+ dialogWindow!!.setFlags(
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ )
+ dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+ requireView().invalidate()
+ }
+ }
+
+ fun setCallListener(videoCallResponseListener: VideoCallResponseListener) {
+ this.videoCallResponseListener = videoCallResponseListener
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View {
+
+ parentView = inflater.inflate(R.layout.activity_video_call, container, false)
+
+ // Objects.requireNonNull(requireActivity().actionBar)!!.hide()
+ arguments?.run {
+ apiKey = getString("apiKey")
+ sessionId = getString("sessionId")
+ token = getString("token")
+ appLang = getString("appLang")
+ baseUrl = getString("baseUrl")
+ sessionStatusModel = getParcelable("sessionStatusModel")
+ }
+ initUI(parentView)
+ requestPermissions()
+
+ handleDragDialog()
+ mDetector = GestureDetectorCompat(context, MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }))
+
+ return parentView
+ }
+
+
+ override fun onPause() {
+ super.onPause()
+ if (mSession == null) {
+ return
+ }
+ mSession!!.onPause()
+ if (requireActivity().isFinishing) {
+ disconnectSession()
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (mSession == null) {
+ return
+ }
+ mSession!!.onResume()
+ }
+
+ override fun onDestroy() {
+ disconnectSession()
+ cmTimer.stop()
+ super.onDestroy()
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private fun initUI(view: View) {
+ videoCallContainer = view.findViewById(R.id.video_call_ll)
+ layoutName = view.findViewById(R.id.layout_name)
+ layoutMini = view.findViewById(R.id.layout_mini)
+ icMini = view.findViewById(R.id.ic_mini)
+ thumbnail_container = view.findViewById(R.id.thumbnail_container)
+ mPublisherViewContainer = view.findViewById(R.id.local_video_view_container)
+ mPublisherViewIcon = view.findViewById(R.id.local_video_view_icon)
+ mSubscriberViewIcon = view.findViewById(R.id.remote_video_view_icon)
+ mSubscriberViewContainer = view.findViewById(R.id.remote_video_view_container)
+
+ patientName = view.findViewById(R.id.patient_name)
+ patientName.text = sessionStatusModel!!.patientName
+
+ cmTimer = view.findViewById(R.id.cmTimer)
+ cmTimer.format = "mm:ss"
+ cmTimer.onChronometerTickListener = Chronometer.OnChronometerTickListener { arg0: Chronometer? ->
+ val minutes: Long
+ val seconds: Long
+ if (!resume) {
+ minutes = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 / 60
+ seconds = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 % 60
+ elapsedTime = SystemClock.elapsedRealtime()
+ } else {
+ minutes = (elapsedTime - cmTimer.base) / 1000 / 60
+ seconds = (elapsedTime - cmTimer.base) / 1000 % 60
+ elapsedTime += 1000
+ }
+ arg0?.text = "$minutes:$seconds"
+ Log.d(VideoCallFragment.TAG, "onChronometerTick: $minutes : $seconds")
+ }
+
+ icMini.setOnClickListener {
+ onMiniCircleClicked()
+ }
+
+ controlPanel = view.findViewById(R.id.control_panel)
+ videoCallPresenter = VideoCallPresenterImpl(this, baseUrl)
+ mCallBtn = view.findViewById(R.id.btn_call)
+ mCallBtn.setOnClickListener {
+ onCallClicked()
+ }
+ btnMinimize = view.findViewById(R.id.btn_minimize)
+ btnMinimize.setOnClickListener {
+ onMinimizedClicked(it)
+ }
+ mCameraBtn = view.findViewById(R.id.btn_camera)
+ mCameraBtn.setOnClickListener {
+ onCameraClicked(it)
+ }
+ mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera)
+ mSwitchCameraBtn.setOnClickListener {
+ onSwitchCameraClicked(it)
+ }
+ mspeckerBtn = view.findViewById(R.id.btn_specker)
+ mspeckerBtn.setOnClickListener {
+ onSpeckerClicked(it)
+ }
+ mMicBtn = view.findViewById(R.id.btn_mic)
+ mMicBtn.setOnClickListener {
+ onMicClicked(it)
+ }
+ // progressBarLayout=findViewById(R.id.progressBar);
+ // progressBar=findViewById(R.id.progress_bar);
+// progressBarTextView=findViewById(R.id.progress_bar_text);
+// progressBar.setVisibility(View.GONE);
+ hiddenButtons()
+ checkClientConnected()
+
+ if (appLang == "ar") {
+ progressBarLayout!!.layoutDirection = View.LAYOUT_DIRECTION_RTL
+ }
+ }
+
+ private fun checkClientConnected() {
+ mConnectedHandler = Handler((Looper.getMainLooper()))
+ mConnectedRunnable = Runnable {
+ if (!isConnected) {
+ videoCallPresenter.callClintConnected(sessionStatusModel)
+ }
+ }
+ mConnectedHandler!!.postDelayed(mConnectedRunnable!!, (55 * 1000).toLong())
+ }
+
+ private fun hiddenButtons() {
+ mVolHandler = Handler()
+ mVolRunnable = Runnable { controlPanel.visibility = View.GONE }
+ mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong())
+ }
+
+ override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
+ }
+
+ override fun onPermissionsGranted(requestCode: Int, perms: List) {
+ Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size)
+ }
+
+ override fun onPermissionsDenied(requestCode: Int, perms: List) {
+ Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size)
+ if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
+ AppSettingsDialog.Builder(this)
+ .setTitle(getString(R.string.title_settings_dialog))
+ .setRationale(getString(R.string.rationale_ask_again))
+ .setPositiveButton(getString(R.string.setting))
+ .setNegativeButton(getString(R.string.cancel))
+ .setRequestCode(RC_SETTINGS_SCREEN_PERM)
+ .build()
+ .show()
+ }
+ }
+
+ @AfterPermissionGranted(RC_VIDEO_APP_PERM)
+ private fun requestPermissions() {
+ val perms = arrayOf(Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.CALL_PHONE)
+ if (EasyPermissions.hasPermissions(requireContext(), *perms)) {
+ try {
+ mSession = Session.Builder(context, apiKey, sessionId).build()
+ mSession!!.setSessionListener(this)
+ mSession!!.connect(token)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ } else {
+ EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, *perms)
+ }
+ }
+
+ override fun onConnected(session: Session?) {
+ Log.i(TAG, "Session Connected")
+ mPublisher = Publisher.Builder(requireContext())
+// .name("publisher")
+// .renderer(ThumbnailCircleVideoRenderer(requireContext()))
+ .build()
+ mPublisher!!.setPublisherListener(this)
+ if (mPublisher!!.view is GLSurfaceView) {
+ (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true)
+ }
+
+ mPublisherViewContainer.addView(mPublisher!!.view)
+ mSession!!.publish(mPublisher)
+
+ if (!resume) {
+ cmTimer.base = SystemClock.elapsedRealtime()
+ }
+ cmTimer.start()
+ videoCallResponseListener?.minimizeVideoEvent(true)
+ }
+
+ override fun onDisconnected(session: Session) {
+ Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId)
+ mSession = null
+ cmTimer.stop()
+ disconnectSession()
+ videoCallResponseListener?.minimizeVideoEvent(false)
+ }
+
+ override fun onError(session: Session, opentokError: OpentokError) {
+ Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId)
+
+ // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in session ")
+// dialog?.dismiss()
+ }
+
+ override fun onStreamReceived(session: Session, stream: Stream) {
+ Log.d(TAG, "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId)
+ if (mSubscriber != null) {
+ isConnected = true
+ return
+ }
+ isConnected = true
+ subscribeToStream(stream)
+ if (mConnectedHandler != null && mConnectedRunnable != null)
+ mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!)
+ videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(3, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
+ }
+
+ override fun onStreamDropped(session: Session, stream: Stream) {
+ Log.d(TAG, "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId)
+ if (mSubscriber == null) {
+ return
+ }
+ if (mSubscriber!!.stream == stream) {
+ mSubscriberViewContainer.removeView(mSubscriber!!.view)
+ mSubscriber!!.destroy()
+ mSubscriber = null
+ }
+ disconnectSession()
+ }
+
+ override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) {
+ Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created")
+ }
+
+ override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) {
+ Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed")
+ }
+
+ override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) {
+ Log.d(VideoCallFragment.TAG, "onError: Error (" + opentokError.message + ") in publisher")
+ // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher")
+// dialog?.dismiss()
+ }
+
+ override fun onVideoDataReceived(subscriberKit: SubscriberKit?) {
+ mSubscriber!!.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
+ (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false)
+ mSubscriberViewContainer.addView(mSubscriber!!.view)
+// switchToThumbnailCircle()
+ }
+
+ fun switchToThumbnailCircle() {
+ thumbnail_container.postDelayed({
+ val view = mSubscriber!!.view
+ if (view.parent != null) {
+ (view.parent as ViewGroup).removeView(view)
+ }
+ if (view is GLSurfaceView) {
+ view.setZOrderOnTop(true)
+ if (mSubscriber!!.renderer is DynamicVideoRenderer) {
+ (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(true)
+ thumbnail_container.addView(view)
+ }
+ }
+ switchToFullScreenView()
+ }, 4000)
+ }
+
+ fun switchToFullScreenView() {
+ mSubscriberViewContainer.postDelayed({
+ val view = mSubscriber!!.view
+ if (view.parent != null) {
+ (view.parent as ViewGroup).removeView(view)
+ }
+ if (view is GLSurfaceView) {
+ view.setZOrderOnTop(false)
+ if (mSubscriber!!.renderer is DynamicVideoRenderer) {
+ (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false)
+ mSubscriberViewContainer.addView(view)
+ }
+ }
+ switchToThumbnailCircle()
+ }, 4000)
+ }
+
+ override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) {}
+
+ override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) {}
+
+ override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {}
+
+ override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {}
+
+ private fun subscribeToStream(stream: Stream) {
+ mSubscriber = Subscriber.Builder(requireContext(), stream)
+ .renderer(DynamicVideoRenderer(requireContext()))
+ .build()
+ mSubscriber!!.setVideoListener(this)
+ mSession!!.subscribe(mSubscriber)
+ }
+
+ private fun disconnectSession() {
+ if (mSession == null) {
+ videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED)
+// requireActivity().setResult(Activity.RESULT_CANCELED)
+ dialog?.dismiss()
+ return
+ }
+
+ if (mSubscriber != null) {
+ mSubscriberViewContainer.removeView(mSubscriber!!.view)
+ mSession!!.unsubscribe(mSubscriber)
+ mSubscriber!!.destroy()
+ mSubscriber = null
+ }
+ if (mPublisher != null) {
+ mPublisherViewContainer.removeView(mPublisher!!.view)
+ mSession!!.unpublish(mPublisher)
+ mPublisher!!.destroy()
+ mPublisher = null
+ }
+ mSession!!.disconnect()
+ countDownTimer?.cancel()
+
+ videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(16, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
+ dialog?.dismiss()
+ }
+
+ override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) {
+ if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) {
+ val returnIntent = Intent()
+ returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel)
+ videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent)
+// requireActivity().setResult(Activity.RESULT_OK, returnIntent)
+ dialog?.dismiss()
+ }
+ }
+
+ override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {}
+
+ override fun onFailure() {}
+
+ private fun onSwitchCameraClicked(view: View?) {
+ if (mPublisher != null) {
+ isSwitchCameraClicked = !isSwitchCameraClicked
+ mPublisher!!.cycleCamera()
+ val res = if (isSwitchCameraClicked) R.drawable.camera_front else R.drawable.camera_back
+ mSwitchCameraBtn.setImageResource(res)
+ }
+ }
+
+ fun onCallClicked() {
+ disconnectSession()
+ }
+
+ private fun miniCircleDoubleTap() {
+ if (isCircle) {
+ onMiniCircleClicked()
+ }
+ }
+
+ private fun onMiniCircleClicked() {
+ if (isCircle) {
+ dialog?.window?.setLayout(
+ 400,
+ 600
+ )
+ } else {
+ dialog?.window?.setLayout(
+ 300,
+ 300
+ )
+ }
+ isCircle = !isCircle
+
+ if (mSubscriber != null) {
+ (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle)
+ } else {
+ if (isCircle) {
+ videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape)
+ mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape)
+ } else {
+ videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color))
+ mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color))
+ }
+
+ }
+
+ if (isCircle) {
+ controlPanel.visibility = View.GONE
+ layoutMini.visibility = View.GONE
+ } else {
+ controlPanel.visibility = View.VISIBLE
+ layoutMini.visibility = View.VISIBLE
+ }
+ }
+
+ private fun onMinimizedClicked(view: View?) {
+ if (isFullScreen) {
+ dialog?.window?.setLayout(
+ 400,
+ 600
+ )
+ } else {
+ dialog?.window?.setLayout(
+ LinearLayout.LayoutParams.MATCH_PARENT,
+ LinearLayout.LayoutParams.MATCH_PARENT
+ )
+ }
+ isFullScreen = !isFullScreen
+
+ val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand
+ btnMinimize.setImageResource(res)
+ setViewsVisibility()
+
+// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen)
+ }
+
+ private fun setViewsVisibility() {
+ val iconSize: Int = context!!.resources.getDimension(R.dimen.video_icon_size).toInt()
+ val iconSizeSmall: Int = context!!.resources.getDimension(R.dimen.video_icon_size_small).toInt()
+ val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = btnMinimize.layoutParams as ConstraintLayout.LayoutParams
+ val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = mCallBtn.layoutParams as ConstraintLayout.LayoutParams
+
+ val localPreviewMargin: Int = context!!.resources.getDimension(R.dimen.local_preview_margin_top).toInt()
+ val localPreviewWidth: Int = context!!.resources.getDimension(R.dimen.local_preview_width).toInt()
+ val localPreviewHeight: Int = context!!.resources.getDimension(R.dimen.local_preview_height).toInt()
+// val localPreviewIconSize: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size).toInt()
+// val localPreviewMarginSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_margin_small).toInt()
+// val localPreviewWidthSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_width_small).toInt()
+// val localPreviewHeightSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_height_small).toInt()
+// val localPreviewIconSmall: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size_small).toInt()
+// val localPreviewLayoutIconParam : FrameLayout.LayoutParams
+ val localPreviewLayoutParam: RelativeLayout.LayoutParams = mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams
+
+ val remotePreviewIconSize: Int = context!!.resources.getDimension(R.dimen.remote_back_icon_size).toInt()
+ val remotePreviewIconSizeSmall: Int = context!!.resources.getDimension(R.dimen.remote_back_icon_size_small).toInt()
+ val remotePreviewLayoutParam: FrameLayout.LayoutParams = mSubscriberViewIcon.layoutParams as FrameLayout.LayoutParams
+
+ if (isFullScreen) {
+ layoutName.visibility = View.VISIBLE
+ layoutMini.visibility = View.GONE
+ mCameraBtn.visibility = View.VISIBLE
+ mSwitchCameraBtn.visibility = View.VISIBLE
+// mspeckerBtn.visibility = View.VISIBLE
+ mMicBtn.visibility = View.VISIBLE
+
+ btnMinimizeLayoutParam.width = iconSize
+ btnMinimizeLayoutParam.height = iconSize
+ mCallBtnLayoutParam.width = iconSize
+ mCallBtnLayoutParam.height = iconSize
+// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSize, localPreviewIconSize)
+//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidth, localPreviewHeight)
+ localPreviewLayoutParam.width = localPreviewWidth
+ localPreviewLayoutParam.height = localPreviewHeight
+ localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0)
+// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSize, remotePreviewIconSize)
+ remotePreviewLayoutParam.width = remotePreviewIconSize
+ remotePreviewLayoutParam.height = remotePreviewIconSize
+ } else {
+ layoutName.visibility = View.GONE
+ layoutMini.visibility = View.VISIBLE
+ mCameraBtn.visibility = View.GONE
+ mSwitchCameraBtn.visibility = View.GONE
+// mspeckerBtn.visibility = View.GONE
+ mMicBtn.visibility = View.GONE
+// mPublisherViewContainer.visibility = View.GONE
+// mPublisherViewIcon.visibility = View.GONE
+
+// layoutParam = ConstraintLayout.LayoutParams(iconSizeSmall, iconSizeSmall)
+ btnMinimizeLayoutParam.width = iconSizeSmall
+ btnMinimizeLayoutParam.height = iconSizeSmall
+ mCallBtnLayoutParam.width = iconSizeSmall
+ mCallBtnLayoutParam.height = iconSizeSmall
+
+ localPreviewLayoutParam.width = 0
+ localPreviewLayoutParam.height = 0
+ localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0)
+// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSmall, localPreviewIconSmall)
+//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidthSmall, localPreviewHeightSmall)
+// localPreviewLayoutParam.width = localPreviewWidthSmall
+// localPreviewLayoutParam.height = localPreviewWidthSmall
+// localPreviewLayoutParam.setMargins(0,localPreviewMarginSmall, localPreviewMarginSmall, 0)
+// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSizeSmall, remotePreviewIconSizeSmall)
+ remotePreviewLayoutParam.width = remotePreviewIconSizeSmall
+ remotePreviewLayoutParam.height = remotePreviewIconSizeSmall
+
+ if (isCircle) {
+ controlPanel.visibility = View.GONE
+ layoutMini.visibility = View.GONE
+ } else {
+ controlPanel.visibility = View.VISIBLE
+ layoutMini.visibility = View.VISIBLE
+ }
+ }
+
+ mPublisherViewContainer.layoutParams = localPreviewLayoutParam
+// mPublisherViewIcon.layoutParams = localPreviewLayoutIconParam
+ mSubscriberViewIcon.layoutParams = remotePreviewLayoutParam
+
+ btnMinimize.layoutParams = btnMinimizeLayoutParam
+ mCallBtn.layoutParams = mCallBtnLayoutParam
+ }
+
+ private fun onCameraClicked(view: View?) {
+ if (mPublisher != null) {
+ isCameraClicked = !isCameraClicked
+ mPublisher!!.publishVideo = !isCameraClicked
+ val res = if (isCameraClicked) R.drawable.video_disabled else R.drawable.video_enabled
+ mCameraBtn!!.setImageResource(res)
+ }
+ }
+
+ private fun onMicClicked(view: View?) {
+ if (mPublisher != null) {
+ isMicClicked = !isMicClicked
+ mPublisher!!.publishAudio = !isMicClicked
+ val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled
+ mMicBtn!!.setImageResource(res)
+ }
+ }
+
+ private fun onSpeckerClicked(view: View?) {
+ if (mSubscriber != null) {
+ isSpeckerClicked = !isSpeckerClicked
+ mSubscriber!!.subscribeToAudio = !isSpeckerClicked
+ val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled
+ mspeckerBtn.setImageResource(res)
+ }
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private fun handleDragDialog() {
+ mWindowManager = requireActivity().getSystemService(Context.WINDOW_SERVICE) as WindowManager
+ getWindowManagerDefaultDisplay()
+
+ videoCallContainer.setOnTouchListener(dragListener)
+ mSubscriberViewContainer.setOnTouchListener(dragListener)
+ }
+
+ @SuppressLint("ClickableViewAccessibility")
+ private val dragListener: View.OnTouchListener = View.OnTouchListener { _, event ->
+ mDetector.onTouchEvent(event)
+
+ //Get Floating widget view params
+ val layoutParams: WindowManager.LayoutParams = dialog!!.window!!.attributes
+ //get the touch location coordinates
+ val x_cord = event.rawX.toInt()
+ val y_cord = event.rawY.toInt()
+ val x_cord_Destination: Int
+ var y_cord_Destination: Int
+
+ when (event.action) {
+ MotionEvent.ACTION_DOWN -> {
+ x_init_cord = x_cord
+ y_init_cord = y_cord
+
+ //remember the initial position.
+ x_init_margin = layoutParams.x
+ y_init_margin = layoutParams.y
+ }
+ MotionEvent.ACTION_UP -> {
+ //Get the difference between initial coordinate and current coordinate
+ val x_diff: Int = x_cord - x_init_cord
+ val y_diff: Int = y_cord - y_init_cord
+
+ y_cord_Destination = y_init_margin + y_diff
+ val barHeight: Int = getStatusBarHeight()
+ if (y_cord_Destination < 0) {
+// y_cord_Destination = 0
+// y_cord_Destination =
+// -(szWindow.y - (videoCallContainer.height /*+ barHeight*/))
+ y_cord_Destination = -(szWindow.y / 2)
+ } else if (y_cord_Destination + (videoCallContainer.height + barHeight) > szWindow.y) {
+// y_cord_Destination = szWindow.y - (videoCallContainer.height + barHeight)
+ y_cord_Destination = (szWindow.y / 2)
+ }
+ layoutParams.y = y_cord_Destination
+
+ //reset position if user drags the floating view
+ resetPosition(x_cord)
+ }
+ MotionEvent.ACTION_MOVE -> {
+ val x_diff_move: Int = x_cord - x_init_cord
+ val y_diff_move: Int = y_cord - y_init_cord
+ x_cord_Destination = x_init_margin + x_diff_move
+ y_cord_Destination = y_init_margin + y_diff_move
+
+ layoutParams.x = x_cord_Destination
+ layoutParams.y = y_cord_Destination
+
+ dialog!!.window!!.attributes = layoutParams
+ }
+ }
+ true
+ }
+
+ private fun showControlPanelTemporarily() {
+ if (!isCircle) {
+ controlPanel.visibility = View.VISIBLE
+ mVolHandler!!.removeCallbacks(mVolRunnable!!)
+ mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong())
+ }
+ }
+
+ /* Reset position of Floating Widget view on dragging */
+ private fun resetPosition(x_cord_now: Int) {
+ if (x_cord_now <= szWindow.x / 2) {
+ isLeft = true
+ moveToLeft(x_cord_now)
+ } else {
+ isLeft = false
+ moveToRight(x_cord_now)
+ }
+ }
+
+ /* Method to move the Floating widget view to Left */
+ private fun moveToLeft(current_x_cord: Int) {
+
+ var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes
+
+ mParams.x =
+ (szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt()
+
+ dialog!!.window!!.attributes = mParams
+ val x = szWindow.x - current_x_cord
+ object : CountDownTimer(500, 5) {
+ //get params of Floating Widget view
+ var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes
+ override fun onTick(t: Long) {
+ val step = (500 - t) / 5
+ // mParams.x = 0 - (current_x_cord * current_x_cord * step).toInt()
+ mParams.x =
+ (szWindow.x - current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
+
+ dialog!!.window!!.attributes = mParams
+ }
+
+ override fun onFinish() {
+ mParams.x = -(szWindow.x - videoCallContainer.width)
+
+ dialog!!.window!!.attributes = mParams
+ }
+ }.start()
+ }
+
+ /* Method to move the Floating widget view to Right */
+ private fun moveToRight(current_x_cord: Int) {
+// var mParams : WindowManager.LayoutParams = dialog!!.window!!.attributes
+// mParams.x =
+// (szWindow.x + current_x_cord * current_x_cord - videoCallContainer.width).toInt()
+//
+// dialog!!.window!!.attributes = mParams
+ object : CountDownTimer(500, 5) {
+ //get params of Floating Widget view
+ var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes
+ override fun onTick(t: Long) {
+ val step = (500 - t) / 5
+ mParams.x =
+ (szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
+
+ dialog!!.window!!.attributes = mParams
+ }
+
+ override fun onFinish() {
+ mParams.x = szWindow.x - videoCallContainer.width
+
+ dialog!!.window!!.attributes = mParams
+ }
+ }.start()
+ }
+
+ private fun getWindowManagerDefaultDisplay() {
+ mWindowManager.getDefaultDisplay()
+ .getSize(szWindow)
+ }
+
+ /* return status bar height on basis of device display metrics */
+ private fun getStatusBarHeight(): Int {
+ return ceil(
+ (25 * requireActivity().applicationContext.resources.displayMetrics.density).toDouble()
+ ).toInt()
+ }
+
+ private class MyGestureListener(val onTabCall: () -> Unit, val miniCircleDoubleTap: () -> Unit) : GestureDetector.SimpleOnGestureListener() {
+
+ override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
+ onTabCall()
+ return true
+ }
+
+ override fun onDoubleTap(e: MotionEvent?): Boolean {
+ miniCircleDoubleTap()
+ return super.onDoubleTap(e)
+ }
+
+ }
+
+ companion object {
+ @JvmStatic
+ fun newInstance(args: Bundle) =
+ VideoCallFragment().apply {
+ arguments = args
+ }
+
+ private val TAG = VideoCallFragment::class.java.simpleName
+
+ private const val RC_SETTINGS_SCREEN_PERM = 123
+ private const val RC_VIDEO_APP_PERM = 124
+
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/util/DynamicVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/DynamicVideoRenderer.kt
new file mode 100644
index 00000000..1a307eb5
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/DynamicVideoRenderer.kt
@@ -0,0 +1,379 @@
+package com.hmg.hmgDr.util
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.PixelFormat
+import android.opengl.GLES20
+import android.opengl.GLSurfaceView
+import android.opengl.Matrix
+import android.view.View
+import com.opentok.android.BaseVideoRenderer
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import java.nio.FloatBuffer
+import java.nio.ShortBuffer
+import java.util.concurrent.locks.ReentrantLock
+import javax.microedition.khronos.egl.EGLConfig
+import javax.microedition.khronos.opengles.GL10
+
+/*
+* https://nhancv.medium.com/android-how-to-make-a-circular-view-as-a-thumbnail-of-opentok-27992aee15c9
+* to solve make circle video stream
+* */
+
+class DynamicVideoRenderer(private val mContext: Context) : BaseVideoRenderer() {
+ private val mView: GLSurfaceView = GLSurfaceView(mContext)
+ private val mRenderer: MyRenderer
+
+ interface DynamicVideoRendererMetadataListener {
+ fun onMetadataReady(metadata: ByteArray?)
+ }
+
+ fun setDynamicVideoRendererMetadataListener(metadataListener: DynamicVideoRendererMetadataListener?) {
+ mRenderer.metadataListener = metadataListener
+ }
+
+ fun enableThumbnailCircle(enable: Boolean) {
+ mRenderer.requestEnableThumbnailCircle = enable
+ }
+
+ internal class MyRenderer : GLSurfaceView.Renderer {
+ var mTextureIds = IntArray(3)
+ var mScaleMatrix = FloatArray(16)
+ private val mVertexBuffer: FloatBuffer
+ private val mTextureBuffer: FloatBuffer
+ private val mDrawListBuffer: ShortBuffer
+ var requestEnableThumbnailCircle = false
+ var mVideoFitEnabled = true
+ var mVideoDisabled = false
+ private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw
+
+ // vertices
+ private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition;
+attribute vec2 aTextureCoord;
+varying vec2 vTextureCoord;
+void main() {
+ gl_Position = uMVPMatrix * aPosition;
+ vTextureCoord = aTextureCoord;
+}
+"""
+ private val fragmentShaderCode = """precision mediump float;
+uniform sampler2D Ytex;
+uniform sampler2D Utex,Vtex;
+uniform int enableCircle;
+uniform vec2 radiusDp;
+varying vec2 vTextureCoord;
+void main(void) {
+ float nx,ny,r,g,b,y,u,v;
+ mediump vec4 txl,ux,vx; nx=vTextureCoord[0];
+ ny=vTextureCoord[1];
+ y=texture2D(Ytex,vec2(nx,ny)).r;
+ u=texture2D(Utex,vec2(nx,ny)).r;
+ v=texture2D(Vtex,vec2(nx,ny)).r;
+ y=1.1643*(y-0.0625);
+ u=u-0.5;
+ v=v-0.5;
+ r=y+1.5958*v;
+ g=y-0.39173*u-0.81290*v;
+ b=y+2.017*u;
+ if (enableCircle > 0) {
+ float radius = 0.5;
+ vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
+ vec4 color1 = vec4(r, g, b, 1.0);
+ vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5));
+ float t = 1.0;
+ if (dist < 0.0) t = 0.0;
+ gl_FragColor = mix(color0, color1, t);
+ }
+ else {
+ gl_FragColor = vec4(r, g, b, 1.0);
+ }
+}
+"""
+ var mFrameLock = ReentrantLock()
+ var mCurrentFrame: Frame? = null
+ private var mProgram = 0
+ private var mTextureWidth = 0
+ private var mTextureHeight = 0
+ private var mViewportWidth = 0
+ private var mViewportHeight = 0
+ override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
+ gl.glClearColor(0f, 0f, 0f, 1f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
+ vertexShaderCode)
+ val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
+ fragmentShaderCode)
+ mProgram = GLES20.glCreateProgram() // create empty OpenGL ES
+ // Program
+ GLES20.glAttachShader(mProgram, vertexShader) // add the vertex
+ // shader to program
+ GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment
+ // shader to
+ // program
+ GLES20.glLinkProgram(mProgram)
+ val positionHandle = GLES20.glGetAttribLocation(mProgram,
+ "aPosition")
+ val textureHandle = GLES20.glGetAttribLocation(mProgram,
+ "aTextureCoord")
+ GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
+ GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4,
+ mVertexBuffer)
+ GLES20.glEnableVertexAttribArray(positionHandle)
+ GLES20.glVertexAttribPointer(textureHandle,
+ TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
+ TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer)
+ GLES20.glEnableVertexAttribArray(textureHandle)
+ GLES20.glUseProgram(mProgram)
+ var i = GLES20.glGetUniformLocation(mProgram, "Ytex")
+ GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */
+ i = GLES20.glGetUniformLocation(mProgram, "Utex")
+ GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */
+ i = GLES20.glGetUniformLocation(mProgram, "Vtex")
+ GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */
+ val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp")
+ val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt()
+ GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat())
+ mTextureWidth = 0
+ mTextureHeight = 0
+ }
+
+ fun enableThumbnailCircle(enable: Boolean) {
+ GLES20.glUseProgram(mProgram)
+ val enableCircleLocation = GLES20.glGetUniformLocation(mProgram, "enableCircle")
+ GLES20.glUniform1i(enableCircleLocation, if (enable) 1 else 0)
+ }
+
+ fun setupTextures(frame: Frame) {
+ if (mTextureIds[0] != 0) {
+ GLES20.glDeleteTextures(3, mTextureIds, 0)
+ }
+ GLES20.glGenTextures(3, mTextureIds, 0)
+ val w = frame.width
+ val h = frame.height
+ val hw = w + 1 shr 1
+ val hh = h + 1 shr 1
+ initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h)
+ initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh)
+ initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh)
+ mTextureWidth = frame.width
+ mTextureHeight = frame.height
+ }
+
+ fun updateTextures(frame: Frame) {
+ val width = frame.width
+ val height = frame.height
+ val half_width = width + 1 shr 1
+ val half_height = height + 1 shr 1
+ val y_size = width * height
+ val uv_size = half_width * half_height
+ val bb = frame.buffer
+ // If we are reusing this frame, make sure we reset position and
+ // limit
+ bb.clear()
+ if (bb.remaining() == y_size + uv_size * 2) {
+ bb.position(0)
+ GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1)
+ GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width,
+ height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
+ bb)
+ bb.position(y_size)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
+ half_width, half_height, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, bb)
+ bb.position(y_size + uv_size)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE2)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
+ half_width, half_height, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, bb)
+ } else {
+ mTextureWidth = 0
+ mTextureHeight = 0
+ }
+ }
+
+ override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
+ GLES20.glViewport(0, 0, width, height)
+ mViewportWidth = width
+ mViewportHeight = height
+ }
+
+ var metadataListener: DynamicVideoRendererMetadataListener? = null
+ override fun onDrawFrame(gl: GL10) {
+ gl.glClearColor(0f, 0f, 0f, 0f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ mFrameLock.lock()
+ if (mCurrentFrame != null && !mVideoDisabled) {
+ GLES20.glUseProgram(mProgram)
+ if (mTextureWidth != mCurrentFrame!!.width
+ || mTextureHeight != mCurrentFrame!!.height) {
+ setupTextures(mCurrentFrame!!)
+ }
+ updateTextures(mCurrentFrame!!)
+ Matrix.setIdentityM(mScaleMatrix, 0)
+ var scaleX = 1.0f
+ var scaleY = 1.0f
+ val ratio = (mCurrentFrame!!.width.toFloat()
+ / mCurrentFrame!!.height)
+ val vratio = mViewportWidth.toFloat() / mViewportHeight
+ if (mVideoFitEnabled) {
+ if (ratio > vratio) {
+ scaleY = vratio / ratio
+ } else {
+ scaleX = ratio / vratio
+ }
+ } else {
+ if (ratio < vratio) {
+ scaleY = vratio / ratio
+ } else {
+ scaleX = ratio / vratio
+ }
+ }
+ Matrix.scaleM(mScaleMatrix, 0,
+ scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f,
+ scaleY, 1f)
+ metadataListener?.onMetadataReady(mCurrentFrame!!.metadata)
+ val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
+ "uMVPMatrix")
+ GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
+ mScaleMatrix, 0)
+ enableThumbnailCircle(requestEnableThumbnailCircle)
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size,
+ GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer)
+ } else {
+ //black frame when video is disabled
+ gl.glClearColor(0f, 0f, 0f, 1f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ }
+ mFrameLock.unlock()
+ }
+
+ fun displayFrame(frame: Frame?) {
+ mFrameLock.lock()
+ if (mCurrentFrame != null) {
+ mCurrentFrame!!.recycle()
+ }
+ mCurrentFrame = frame
+ mFrameLock.unlock()
+ }
+
+ fun disableVideo(b: Boolean) {
+ mFrameLock.lock()
+ mVideoDisabled = b
+ if (mVideoDisabled) {
+ if (mCurrentFrame != null) {
+ mCurrentFrame!!.recycle()
+ }
+ mCurrentFrame = null
+ }
+ mFrameLock.unlock()
+ }
+
+ fun enableVideoFit(enableVideoFit: Boolean) {
+ mVideoFitEnabled = enableVideoFit
+ }
+
+ companion object {
+ // number of coordinates per vertex in this array
+ const val COORDS_PER_VERTEX = 3
+ const val TEXTURECOORDS_PER_VERTEX = 2
+ var mXYZCoords = floatArrayOf(
+ -1.0f, 1.0f, 0.0f, // top left
+ -1.0f, -1.0f, 0.0f, // bottom left
+ 1.0f, -1.0f, 0.0f, // bottom right
+ 1.0f, 1.0f, 0.0f // top right
+ )
+ var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f)
+ fun initializeTexture(name: Int, id: Int, width: Int, height: Int) {
+ GLES20.glActiveTexture(name)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id)
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
+ width, height, 0, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, null)
+ }
+
+ fun loadShader(type: Int, shaderCode: String?): Int {
+ val shader = GLES20.glCreateShader(type)
+ GLES20.glShaderSource(shader, shaderCode)
+ GLES20.glCompileShader(shader)
+ return shader
+ }
+ }
+
+ init {
+ val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4)
+ bb.order(ByteOrder.nativeOrder())
+ mVertexBuffer = bb.asFloatBuffer()
+ mVertexBuffer.put(mXYZCoords)
+ mVertexBuffer.position(0)
+ val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4)
+ tb.order(ByteOrder.nativeOrder())
+ mTextureBuffer = tb.asFloatBuffer()
+ mTextureBuffer.put(mUVCoords)
+ mTextureBuffer.position(0)
+ val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2)
+ dlb.order(ByteOrder.nativeOrder())
+ mDrawListBuffer = dlb.asShortBuffer()
+ mDrawListBuffer.put(mVertexIndex)
+ mDrawListBuffer.position(0)
+ }
+ }
+
+ override fun onFrame(frame: Frame) {
+ mRenderer.displayFrame(frame)
+ mView.requestRender()
+ }
+
+ override fun setStyle(key: String, value: String) {
+ if (STYLE_VIDEO_SCALE == key) {
+ if (STYLE_VIDEO_FIT == value) {
+ mRenderer.enableVideoFit(true)
+ } else if (STYLE_VIDEO_FILL == value) {
+ mRenderer.enableVideoFit(false)
+ }
+ }
+ }
+
+ override fun onVideoPropertiesChanged(videoEnabled: Boolean) {
+ mRenderer.disableVideo(!videoEnabled)
+ }
+
+ override fun getView(): View {
+ return mView
+ }
+
+ override fun onPause() {
+ mView.onPause()
+ }
+
+ override fun onResume() {
+ mView.onResume()
+ }
+
+ companion object {
+ private const val THUMBNAIL_SIZE = 90 //in dp
+ }
+
+ init {
+ mView.setEGLContextClientVersion(2)
+ mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)
+ mView.holder.setFormat(PixelFormat.TRANSLUCENT)
+ mRenderer = MyRenderer()
+ mView.setRenderer(mRenderer)
+ mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/util/ThumbnailCircleVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/ThumbnailCircleVideoRenderer.kt
new file mode 100644
index 00000000..b9b5a245
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/ThumbnailCircleVideoRenderer.kt
@@ -0,0 +1,357 @@
+package com.hmg.hmgDr.util
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.PixelFormat
+import android.opengl.GLES20
+import android.opengl.GLSurfaceView
+import android.opengl.Matrix
+import android.view.View
+import com.opentok.android.BaseVideoRenderer
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import java.nio.FloatBuffer
+import java.nio.ShortBuffer
+import java.util.concurrent.locks.ReentrantLock
+import javax.microedition.khronos.egl.EGLConfig
+import javax.microedition.khronos.opengles.GL10
+
+
+class ThumbnailCircleVideoRenderer(private val mContext: Context) : BaseVideoRenderer() {
+ private val mView: GLSurfaceView = GLSurfaceView(mContext)
+ private val mRenderer: MyRenderer
+
+ interface ThumbnailCircleVideoRendererMetadataListener {
+ fun onMetadataReady(metadata: ByteArray?)
+ }
+
+ fun setThumbnailCircleVideoRendererMetadataListener(metadataListener: ThumbnailCircleVideoRendererMetadataListener?) {
+ mRenderer.metadataListener = metadataListener
+ }
+
+ internal class MyRenderer : GLSurfaceView.Renderer {
+ var mTextureIds = IntArray(3)
+ var mScaleMatrix = FloatArray(16)
+ private val mVertexBuffer: FloatBuffer
+ private val mTextureBuffer: FloatBuffer
+ private val mDrawListBuffer: ShortBuffer
+ var mVideoFitEnabled = true
+ var mVideoDisabled = false
+ private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw
+
+ // vertices
+ private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition;
+attribute vec2 aTextureCoord;
+varying vec2 vTextureCoord;
+void main() {
+ gl_Position = uMVPMatrix * aPosition;
+ vTextureCoord = aTextureCoord;
+}
+"""
+ private val fragmentShaderCode = """precision mediump float;
+uniform sampler2D Ytex;
+uniform sampler2D Utex,Vtex;
+uniform vec2 radiusDp;
+varying vec2 vTextureCoord;
+void main(void) {
+ float nx,ny,r,g,b,y,u,v;
+ mediump vec4 txl,ux,vx; nx=vTextureCoord[0];
+ ny=vTextureCoord[1];
+ y=texture2D(Ytex,vec2(nx,ny)).r;
+ u=texture2D(Utex,vec2(nx,ny)).r;
+ v=texture2D(Vtex,vec2(nx,ny)).r;
+ y=1.1643*(y-0.0625);
+ u=u-0.5;
+ v=v-0.5;
+ r=y+1.5958*v;
+ g=y-0.39173*u-0.81290*v;
+ b=y+2.017*u;
+ float radius = 0.5;
+ vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
+ vec4 color1 = vec4(r, g, b, 1.0);
+ vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5));
+ float t = 1.0;
+ if (dist < 0.0) t = 0.0;
+ gl_FragColor = mix(color0, color1, t);
+}
+"""
+ var mFrameLock = ReentrantLock()
+ var mCurrentFrame: Frame? = null
+ private var mProgram = 0
+ private var mTextureWidth = 0
+ private var mTextureHeight = 0
+ private var mViewportWidth = 0
+ private var mViewportHeight = 0
+ override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
+ gl.glClearColor(0f, 0f, 0f, 1f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
+ vertexShaderCode)
+ val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
+ fragmentShaderCode)
+ mProgram = GLES20.glCreateProgram() // create empty OpenGL ES
+ // Program
+ GLES20.glAttachShader(mProgram, vertexShader) // add the vertex
+ // shader to program
+ GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment
+ // shader to
+ // program
+ GLES20.glLinkProgram(mProgram)
+ val positionHandle = GLES20.glGetAttribLocation(mProgram,
+ "aPosition")
+ val textureHandle = GLES20.glGetAttribLocation(mProgram,
+ "aTextureCoord")
+ GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
+ GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4,
+ mVertexBuffer)
+ GLES20.glEnableVertexAttribArray(positionHandle)
+ GLES20.glVertexAttribPointer(textureHandle,
+ TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
+ TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer)
+ GLES20.glEnableVertexAttribArray(textureHandle)
+ GLES20.glUseProgram(mProgram)
+ var i = GLES20.glGetUniformLocation(mProgram, "Ytex")
+ GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */
+ i = GLES20.glGetUniformLocation(mProgram, "Utex")
+ GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */
+ i = GLES20.glGetUniformLocation(mProgram, "Vtex")
+ GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */
+ val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp")
+ val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt()
+ GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat())
+ mTextureWidth = 0
+ mTextureHeight = 0
+ }
+
+ fun setupTextures(frame: Frame) {
+ if (mTextureIds[0] != 0) {
+ GLES20.glDeleteTextures(3, mTextureIds, 0)
+ }
+ GLES20.glGenTextures(3, mTextureIds, 0)
+ val w = frame.width
+ val h = frame.height
+ val hw = w + 1 shr 1
+ val hh = h + 1 shr 1
+ initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h)
+ initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh)
+ initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh)
+ mTextureWidth = frame.width
+ mTextureHeight = frame.height
+ }
+
+ fun updateTextures(frame: Frame) {
+ val width = frame.width
+ val height = frame.height
+ val half_width = width + 1 shr 1
+ val half_height = height + 1 shr 1
+ val y_size = width * height
+ val uv_size = half_width * half_height
+ val bb = frame.buffer
+ // If we are reusing this frame, make sure we reset position and
+ // limit
+ bb.clear()
+ if (bb.remaining() == y_size + uv_size * 2) {
+ bb.position(0)
+ GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1)
+ GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width,
+ height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
+ bb)
+ bb.position(y_size)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
+ half_width, half_height, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, bb)
+ bb.position(y_size + uv_size)
+ GLES20.glActiveTexture(GLES20.GL_TEXTURE2)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2])
+ GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
+ half_width, half_height, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, bb)
+ } else {
+ mTextureWidth = 0
+ mTextureHeight = 0
+ }
+ }
+
+ override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
+ GLES20.glViewport(0, 0, width, height)
+ mViewportWidth = width
+ mViewportHeight = height
+ }
+
+ var metadataListener: ThumbnailCircleVideoRendererMetadataListener? = null
+ override fun onDrawFrame(gl: GL10) {
+ gl.glClearColor(0f, 0f, 0f, 0f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ mFrameLock.lock()
+ if (mCurrentFrame != null && !mVideoDisabled) {
+ GLES20.glUseProgram(mProgram)
+ if (mTextureWidth != mCurrentFrame!!.width
+ || mTextureHeight != mCurrentFrame!!.height) {
+ setupTextures(mCurrentFrame!!)
+ }
+ updateTextures(mCurrentFrame!!)
+ Matrix.setIdentityM(mScaleMatrix, 0)
+ var scaleX = 1.0f
+ var scaleY = 1.0f
+ val ratio = (mCurrentFrame!!.width.toFloat()
+ / mCurrentFrame!!.height)
+ val vratio = mViewportWidth.toFloat() / mViewportHeight
+ if (mVideoFitEnabled) {
+ if (ratio > vratio) {
+ scaleY = vratio / ratio
+ } else {
+ scaleX = ratio / vratio
+ }
+ } else {
+ if (ratio < vratio) {
+ scaleY = vratio / ratio
+ } else {
+ scaleX = ratio / vratio
+ }
+ }
+ Matrix.scaleM(mScaleMatrix, 0,
+ scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f,
+ scaleY, 1f)
+ metadataListener?.onMetadataReady(mCurrentFrame!!.metadata)
+ val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
+ "uMVPMatrix")
+ GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
+ mScaleMatrix, 0)
+ GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size,
+ GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer)
+ } else {
+ //black frame when video is disabled
+ gl.glClearColor(0f, 0f, 0f, 1f)
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
+ }
+ mFrameLock.unlock()
+ }
+
+ fun displayFrame(frame: Frame?) {
+ mFrameLock.lock()
+ if (mCurrentFrame != null) {
+ mCurrentFrame!!.recycle()
+ }
+ mCurrentFrame = frame
+ mFrameLock.unlock()
+ }
+
+ fun disableVideo(b: Boolean) {
+ mFrameLock.lock()
+ mVideoDisabled = b
+ if (mVideoDisabled) {
+ if (mCurrentFrame != null) {
+ mCurrentFrame!!.recycle()
+ }
+ mCurrentFrame = null
+ }
+ mFrameLock.unlock()
+ }
+
+ fun enableVideoFit(enableVideoFit: Boolean) {
+ mVideoFitEnabled = enableVideoFit
+ }
+
+ companion object {
+ // number of coordinates per vertex in this array
+ const val COORDS_PER_VERTEX = 3
+ const val TEXTURECOORDS_PER_VERTEX = 2
+ var mXYZCoords = floatArrayOf(
+ -1.0f, 1.0f, 0.0f, // top left
+ -1.0f, -1.0f, 0.0f, // bottom left
+ 1.0f, -1.0f, 0.0f, // bottom right
+ 1.0f, 1.0f, 0.0f // top right
+ )
+ var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f)
+ fun initializeTexture(name: Int, id: Int, width: Int, height: Int) {
+ GLES20.glActiveTexture(name)
+ GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id)
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
+ GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
+ GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
+ GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
+ width, height, 0, GLES20.GL_LUMINANCE,
+ GLES20.GL_UNSIGNED_BYTE, null)
+ }
+
+ fun loadShader(type: Int, shaderCode: String?): Int {
+ val shader = GLES20.glCreateShader(type)
+ GLES20.glShaderSource(shader, shaderCode)
+ GLES20.glCompileShader(shader)
+ return shader
+ }
+ }
+
+ init {
+ val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4)
+ bb.order(ByteOrder.nativeOrder())
+ mVertexBuffer = bb.asFloatBuffer()
+ mVertexBuffer.put(mXYZCoords)
+ mVertexBuffer.position(0)
+ val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4)
+ tb.order(ByteOrder.nativeOrder())
+ mTextureBuffer = tb.asFloatBuffer()
+ mTextureBuffer.put(mUVCoords)
+ mTextureBuffer.position(0)
+ val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2)
+ dlb.order(ByteOrder.nativeOrder())
+ mDrawListBuffer = dlb.asShortBuffer()
+ mDrawListBuffer.put(mVertexIndex)
+ mDrawListBuffer.position(0)
+ }
+ }
+
+ override fun onFrame(frame: Frame) {
+ mRenderer.displayFrame(frame)
+ mView.requestRender()
+ }
+
+ override fun setStyle(key: String, value: String) {
+ if (STYLE_VIDEO_SCALE == key) {
+ if (STYLE_VIDEO_FIT == value) {
+ mRenderer.enableVideoFit(true)
+ } else if (STYLE_VIDEO_FILL == value) {
+ mRenderer.enableVideoFit(false)
+ }
+ }
+ }
+
+ override fun onVideoPropertiesChanged(videoEnabled: Boolean) {
+ mRenderer.disableVideo(!videoEnabled)
+ }
+
+ override fun getView(): View {
+ return mView
+ }
+
+ override fun onPause() {
+ mView.onPause()
+ }
+
+ override fun onResume() {
+ mView.onResume()
+ }
+
+ companion object {
+ private const val THUMBNAIL_SIZE = 90 //in dp
+ }
+
+ init {
+ mView.setEGLContextClientVersion(2)
+ mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)
+ mView.holder.setFormat(PixelFormat.TRANSLUCENT)
+ mRenderer = MyRenderer()
+ mView.setRenderer(mRenderer)
+ mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
+ }
+}
diff --git a/android/app/src/main/res/drawable/call.png b/android/app/src/main/res/drawable/call.png
index fc00f4f9..52f8e267 100644
Binary files a/android/app/src/main/res/drawable/call.png and b/android/app/src/main/res/drawable/call.png differ
diff --git a/android/app/src/main/res/drawable/camera_back.png b/android/app/src/main/res/drawable/camera_back.png
new file mode 100644
index 00000000..c3d63ac3
Binary files /dev/null and b/android/app/src/main/res/drawable/camera_back.png differ
diff --git a/android/app/src/main/res/drawable/camera_front.png b/android/app/src/main/res/drawable/camera_front.png
new file mode 100644
index 00000000..332ab0f5
Binary files /dev/null and b/android/app/src/main/res/drawable/camera_front.png differ
diff --git a/android/app/src/main/res/drawable/circle_shape.xml b/android/app/src/main/res/drawable/circle_shape.xml
new file mode 100644
index 00000000..27b49f9b
--- /dev/null
+++ b/android/app/src/main/res/drawable/circle_shape.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/expand.png b/android/app/src/main/res/drawable/expand.png
new file mode 100644
index 00000000..7020dc2e
Binary files /dev/null and b/android/app/src/main/res/drawable/expand.png differ
diff --git a/android/app/src/main/res/drawable/flip_disapled.png b/android/app/src/main/res/drawable/flip_disapled.png
deleted file mode 100644
index 5226029e..00000000
Binary files a/android/app/src/main/res/drawable/flip_disapled.png and /dev/null differ
diff --git a/android/app/src/main/res/drawable/flip_enabled.png b/android/app/src/main/res/drawable/flip_enabled.png
deleted file mode 100644
index 152dc10e..00000000
Binary files a/android/app/src/main/res/drawable/flip_enabled.png and /dev/null differ
diff --git a/android/app/src/main/res/drawable/ic_mini.xml b/android/app/src/main/res/drawable/ic_mini.xml
new file mode 100644
index 00000000..128a7430
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_mini.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/layout_rounded_bg.xml b/android/app/src/main/res/drawable/layout_rounded_bg.xml
new file mode 100644
index 00000000..ce73e763
--- /dev/null
+++ b/android/app/src/main/res/drawable/layout_rounded_bg.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/mic_disabled.png b/android/app/src/main/res/drawable/mic_disabled.png
index 3603df75..266cb6c7 100644
Binary files a/android/app/src/main/res/drawable/mic_disabled.png and b/android/app/src/main/res/drawable/mic_disabled.png differ
diff --git a/android/app/src/main/res/drawable/mic_enabled.png b/android/app/src/main/res/drawable/mic_enabled.png
index 5d9aa677..ef7617f7 100644
Binary files a/android/app/src/main/res/drawable/mic_enabled.png and b/android/app/src/main/res/drawable/mic_enabled.png differ
diff --git a/android/app/src/main/res/drawable/reducing.png b/android/app/src/main/res/drawable/reducing.png
new file mode 100644
index 00000000..59f2c9e6
Binary files /dev/null and b/android/app/src/main/res/drawable/reducing.png differ
diff --git a/android/app/src/main/res/drawable/shape_capsule.xml b/android/app/src/main/res/drawable/shape_capsule.xml
new file mode 100644
index 00000000..a5dcdd09
--- /dev/null
+++ b/android/app/src/main/res/drawable/shape_capsule.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/video_disabled.png b/android/app/src/main/res/drawable/video_disabled.png
new file mode 100644
index 00000000..d6ccbe7a
Binary files /dev/null and b/android/app/src/main/res/drawable/video_disabled.png differ
diff --git a/android/app/src/main/res/drawable/video_disanabled.png b/android/app/src/main/res/drawable/video_disanabled.png
deleted file mode 100644
index 5c20c7bd..00000000
Binary files a/android/app/src/main/res/drawable/video_disanabled.png and /dev/null differ
diff --git a/android/app/src/main/res/drawable/video_enabled.png b/android/app/src/main/res/drawable/video_enabled.png
index 23331e30..6fcbe750 100644
Binary files a/android/app/src/main/res/drawable/video_enabled.png and b/android/app/src/main/res/drawable/video_enabled.png differ
diff --git a/android/app/src/main/res/layout/activity_video_call.xml b/android/app/src/main/res/layout/activity_video_call.xml
index 2dcf2ba4..a54e57b3 100644
--- a/android/app/src/main/res/layout/activity_video_call.xml
+++ b/android/app/src/main/res/layout/activity_video_call.xml
@@ -1,169 +1,197 @@
-
+ android:background="@color/text_color"
+ android:orientation="vertical">
+
-
-
+
+
+
+
+ android:layout_alignParentEnd="true"
+ android:background="@drawable/shape_capsule"
+ android:padding="@dimen/padding_space_small">
+
+
+
+
-
+ android:layout_height="0dp"
+ app:layout_constraintBottom_toTopOf="@id/control_panel"
+ app:layout_constraintTop_toBottomOf="@+id/layout_name">
+
+
+
+
+
+
+ android:layout_below="@+id/layout_mini"
+ android:background="@color/remoteBackground">
-
-
-
-
+
-
-
+
-
+
+
+
+
+
+
+
+ android:padding="@dimen/padding_space_big"
+ app:layout_constraintBottom_toBottomOf="parent">
+ android:src="@drawable/call"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+ android:src="@drawable/reducing"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+ android:src="@drawable/video_enabled"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/btn_minimize"
+ app:layout_constraintTop_toTopOf="parent" />
+ android:src="@drawable/mic_enabled"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/btn_camera"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
-
+ android:src="@drawable/audio_enabled"
+ android:visibility="gone"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/btn_mic"
+ app:layout_constraintTop_toTopOf="parent" />
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
index d1d2a305..f52c2cf2 100644
--- a/android/app/src/main/res/values/colors.xml
+++ b/android/app/src/main/res/values/colors.xml
@@ -5,7 +5,17 @@
#fc3850
#e4e9f2
+ #80757575
+ #00ffffff
+
+
#827b92
#484258
+ #FF2E303A
+
+ #fff
+ #000
+ #389842
+ #d51e26
diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml
index 79f3d269..0694f5f4 100644
--- a/android/app/src/main/res/values/dimens.xml
+++ b/android/app/src/main/res/values/dimens.xml
@@ -3,20 +3,39 @@
16dp
16dp
28dp
+ 12dp
24dp
60dp
54dp
+ 52dp
+ 24dp
+
+ 24dp
+ 25dp
88dp
+ 40dp
117dp
+ 50dp
50dp
+ 25dp
100dp
+ 40dp
90dp
-
- 24dp
- 25dp
+
+ 14sp
+ 16sp
+ 22sp
+
+
+ 4dp
+ 8sp
+ 16dp
+ 24dp
+
+
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 74349756..bc694f7c 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -4,5 +4,7 @@
الوقت المتبقي بالثانيه:
Settings
Cancel
+
+ Hello blank fragment
\ No newline at end of file
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 24355fae..e13b5b14 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -16,4 +16,21 @@
- true
- @null
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
index 49bd99ef..4cb72d20 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -16,10 +16,12 @@ allprojects {
repositories {
google()
jcenter()
+ mavenCentral()
maven { url 'https://tokbox.bintray.com/maven' }
}
}
+
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
diff --git a/dart b/dart
new file mode 100644
index 00000000..e69de29b
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 00000000..c2335042
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,92 @@
+# Uncomment this line to define a global platform for your project
+ platform :ios, '11.0'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def parse_KV_file(file, separator='=')
+ file_abs_path = File.expand_path(file)
+ if !File.exists? file_abs_path
+ return [];
+ end
+ generated_key_values = {}
+ skip_line_start_symbols = ["#", "/"]
+ File.foreach(file_abs_path) do |line|
+ next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
+ plugin = line.split(pattern=separator)
+ if plugin.length == 2
+ podname = plugin[0].strip()
+ path = plugin[1].strip()
+ podpath = File.expand_path("#{path}", file_abs_path)
+ generated_key_values[podname] = podpath
+ else
+ puts "Invalid plugin specification: #{line}"
+ end
+ end
+ generated_key_values
+end
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ # Flutter Pod
+
+ copied_flutter_dir = File.join(__dir__, 'Flutter')
+ copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
+ copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
+ unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
+ # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
+ # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
+ # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
+
+ generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+ generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
+ cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
+
+ unless File.exist?(copied_framework_path)
+ FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
+ end
+ unless File.exist?(copied_podspec_path)
+ FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
+ end
+ end
+
+ # Keep pod path relative so it can be checked into Podfile.lock.
+ pod 'Flutter', :path => 'Flutter'
+ pod 'OpenTok'
+ pod 'Alamofire', '~> 5.2'
+ pod 'AADraggableView'
+ # Plugin Pods
+
+ # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
+ # referring to absolute paths on developers' machines.
+ system('rm -rf .symlinks')
+ system('mkdir -p .symlinks/plugins')
+ plugin_pods = parse_KV_file('../.flutter-plugins')
+ plugin_pods.each do |name, path|
+ symlink = File.join('.symlinks', 'plugins', name)
+ File.symlink(path, symlink)
+ pod name, :path => File.join(symlink, 'ios')
+ end
+end
+
+# Prevent Cocoapods from embedding a second Flutter framework and causing an error with the new Xcode build system.
+install! 'cocoapods', :disable_input_output_paths => true
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ target.build_configurations.each do |config|
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
+ end
+ end
+end
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 9efb7e0d..c31cbe8e 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -9,12 +9,16 @@
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
29211E4225C172B700DD740D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 29211E4125C172B700DD740D /* GoogleService-Info.plist */; };
+ 300790FA266FB14B0052174C /* VCEmbeder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300790F9266FB14B0052174C /* VCEmbeder.swift */; };
+ 300790FC26710CAB0052174C /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 300790FB26710CAB0052174C /* Extensions.swift */; };
+ 30F70E6C266F56FD005D8F8E /* MainAppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F70E6B266F56FD005D8F8E /* MainAppViewController.swift */; };
+ 30F70E6F266F6509005D8F8E /* VideoCallRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30F70E6E266F6509005D8F8E /* VideoCallRequestParameters.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
- 9CE61EBD24AB366E008D68DD /* VideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE61EBC24AB366E008D68DD /* VideoViewController.swift */; };
+ 9CE61EBD24AB366E008D68DD /* VideoCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE61EBC24AB366E008D68DD /* VideoCallViewController.swift */; };
9CE61ECD24ADBB4C008D68DD /* ICallProtocoll.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CE61ECC24ADBB4C008D68DD /* ICallProtocoll.swift */; };
B650DC3076E9D70CB188286A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93A5F83B23AB032D1E096663 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
@@ -37,6 +41,10 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
29211CD725C165D600DD740D /* RunnerRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerRelease.entitlements; sourceTree = ""; };
29211E4125C172B700DD740D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
+ 300790F9266FB14B0052174C /* VCEmbeder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VCEmbeder.swift; sourceTree = ""; };
+ 300790FB26710CAB0052174C /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = ""; };
+ 30F70E6B266F56FD005D8F8E /* MainAppViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAppViewController.swift; sourceTree = ""; };
+ 30F70E6E266F6509005D8F8E /* VideoCallRequestParameters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallRequestParameters.swift; sourceTree = ""; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
@@ -50,7 +58,7 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 9CE61EBC24AB366E008D68DD /* VideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoViewController.swift; sourceTree = ""; };
+ 9CE61EBC24AB366E008D68DD /* VideoCallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallViewController.swift; sourceTree = ""; };
9CE61ECC24ADBB4C008D68DD /* ICallProtocoll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICallProtocoll.swift; sourceTree = ""; };
9D4B7DB43C6A6C849D2387CE /* 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 = ""; };
E698D7B14B12DF768FE47A1A /* 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 = ""; };
@@ -68,6 +76,31 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 300790F8266FB0F10052174C /* helpers */ = {
+ isa = PBXGroup;
+ children = (
+ 300790F9266FB14B0052174C /* VCEmbeder.swift */,
+ 300790FB26710CAB0052174C /* Extensions.swift */,
+ );
+ name = helpers;
+ sourceTree = "";
+ };
+ 30F70E6A266F56C9005D8F8E /* controllers */ = {
+ isa = PBXGroup;
+ children = (
+ 30F70E6B266F56FD005D8F8E /* MainAppViewController.swift */,
+ );
+ name = controllers;
+ sourceTree = "";
+ };
+ 30F70E6D266F64F8005D8F8E /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ 30F70E6E266F6509005D8F8E /* VideoCallRequestParameters.swift */,
+ );
+ name = Models;
+ sourceTree = "";
+ };
7D66D387293CE5376A07EC5F /* Pods */ = {
isa = PBXGroup;
children = (
@@ -111,6 +144,9 @@
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
+ 300790F8266FB0F10052174C /* helpers */,
+ 30F70E6D266F64F8005D8F8E /* Models */,
+ 30F70E6A266F56C9005D8F8E /* controllers */,
29211E4125C172B700DD740D /* GoogleService-Info.plist */,
29211CD725C165D600DD740D /* RunnerRelease.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
@@ -122,7 +158,7 @@
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
- 9CE61EBC24AB366E008D68DD /* VideoViewController.swift */,
+ 9CE61EBC24AB366E008D68DD /* VideoCallViewController.swift */,
9CE61ECC24ADBB4C008D68DD /* ICallProtocoll.swift */,
);
path = Runner;
@@ -359,10 +395,14 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 300790FA266FB14B0052174C /* VCEmbeder.swift in Sources */,
+ 30F70E6F266F6509005D8F8E /* VideoCallRequestParameters.swift in Sources */,
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
- 9CE61EBD24AB366E008D68DD /* VideoViewController.swift in Sources */,
+ 300790FC26710CAB0052174C /* Extensions.swift in Sources */,
+ 9CE61EBD24AB366E008D68DD /* VideoCallViewController.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
9CE61ECD24ADBB4C008D68DD /* ICallProtocoll.swift in Sources */,
+ 30F70E6C266F56FD005D8F8E /* MainAppViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index fb2dffc4..a28140cf 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -27,6 +27,8 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
+
+
-
-
+
+
+
+
Bool {
- let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
- let videoCallChannel = FlutterMethodChannel(name: "Dr.cloudSolution/videoCall",
- binaryMessenger: controller.binaryMessenger)
- videoCallChannel.setMethodCallHandler({
- (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
- self.result = result
- switch call.method {
- case "openVideoCall":
- do {
- let arguments = call.arguments as? NSDictionary
- let kApiKey = arguments!["kApiKey"] as? String
- let kSessionId = arguments!["kSessionId"] as? String
- let kToken = arguments!["kToken"] as? String
- let appLang = arguments!["appLang"] as? String
- let vC_ID = arguments!["VC_ID"] as? Int
- let tokenID = arguments!["TokenID"] as? String
- let generalId = arguments!["generalId"] as? String
- let doctorId = arguments!["DoctorId"] as? Int
- let baseUrl = arguments!["baseUrl"] as? String
-
- self.openVideoChat(result: result,kApiKey: kApiKey!,kSessionId:kSessionId!,kToken: kToken!, appLang: appLang!, vC_ID: vC_ID!,tokenID: tokenID!,generalId: generalId!,doctorId: doctorId!, baseUrl: baseUrl!)
- }
- default:
- result(FlutterMethodNotImplemented)
- }
- })
- GeneratedPluginRegistrant.register(with: self)
+ GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
@@ -61,7 +35,7 @@ import OpenTok
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let identifier = "ViewControllerNav"
let navVC = storyboard.instantiateViewController(withIdentifier: identifier) as! UINavigationController
- let videoVC = navVC.viewControllers.first as! ViewController
+ let videoVC = navVC.viewControllers.first as! VideoCallViewController
videoVC.kApiKey=kApiKey
videoVC.kSessionId=kSessionId
videoVC.kToken=kToken
@@ -75,6 +49,6 @@ import OpenTok
navVC.modalPresentationStyle = .fullScreen
window.rootViewController?.present(navVC, animated: true, completion: nil)
-
}
}
+
diff --git a/ios/Runner/Assets.xcassets/Contents.json b/ios/Runner/Assets.xcassets/Contents.json
index da4a164c..73c00596 100755
--- a/ios/Runner/Assets.xcassets/Contents.json
+++ b/ios/Runner/Assets.xcassets/Contents.json
@@ -1,6 +1,6 @@
{
"info" : {
- "version" : 1,
- "author" : "xcode"
+ "author" : "xcode",
+ "version" : 1
}
-}
\ No newline at end of file
+}
diff --git a/ios/Runner/Assets.xcassets/camera_back.imageset/Contents.json b/ios/Runner/Assets.xcassets/camera_back.imageset/Contents.json
new file mode 100644
index 00000000..ab08ef1a
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/camera_back.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "camera_back.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/camera_back.imageset/camera_back.png b/ios/Runner/Assets.xcassets/camera_back.imageset/camera_back.png
new file mode 100644
index 00000000..c3d63ac3
Binary files /dev/null and b/ios/Runner/Assets.xcassets/camera_back.imageset/camera_back.png differ
diff --git a/ios/Runner/Assets.xcassets/camera_front.imageset/Contents.json b/ios/Runner/Assets.xcassets/camera_front.imageset/Contents.json
new file mode 100644
index 00000000..a0e93123
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/camera_front.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "camera_front.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/camera_front.imageset/camera_front.png b/ios/Runner/Assets.xcassets/camera_front.imageset/camera_front.png
new file mode 100644
index 00000000..332ab0f5
Binary files /dev/null and b/ios/Runner/Assets.xcassets/camera_front.imageset/camera_front.png differ
diff --git a/ios/Runner/Assets.xcassets/end_call.imageset/Contents.json b/ios/Runner/Assets.xcassets/end_call.imageset/Contents.json
new file mode 100644
index 00000000..3762a5af
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/end_call.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "end_call.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/end_call.imageset/end_call.png b/ios/Runner/Assets.xcassets/end_call.imageset/end_call.png
new file mode 100644
index 00000000..52f8e267
Binary files /dev/null and b/ios/Runner/Assets.xcassets/end_call.imageset/end_call.png differ
diff --git a/ios/Runner/Assets.xcassets/expand_video.imageset/Contents.json b/ios/Runner/Assets.xcassets/expand_video.imageset/Contents.json
new file mode 100644
index 00000000..1ecfeae9
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/expand_video.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "expand.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/expand_video.imageset/expand.png b/ios/Runner/Assets.xcassets/expand_video.imageset/expand.png
new file mode 100644
index 00000000..7020dc2e
Binary files /dev/null and b/ios/Runner/Assets.xcassets/expand_video.imageset/expand.png differ
diff --git a/ios/Runner/Assets.xcassets/float_video.imageset/Contents.json b/ios/Runner/Assets.xcassets/float_video.imageset/Contents.json
new file mode 100644
index 00000000..e3a2ec5a
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/float_video.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "Group 8024.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/float_video.imageset/Group 8024.png b/ios/Runner/Assets.xcassets/float_video.imageset/Group 8024.png
new file mode 100644
index 00000000..59f2c9e6
Binary files /dev/null and b/ios/Runner/Assets.xcassets/float_video.imageset/Group 8024.png differ
diff --git a/ios/Runner/Assets.xcassets/hide_video_icon.imageset/Contents.json b/ios/Runner/Assets.xcassets/hide_video_icon.imageset/Contents.json
new file mode 100644
index 00000000..91a3b7b1
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/hide_video_icon.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "hide_video_icon.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/hide_video_icon.imageset/hide_video_icon.png b/ios/Runner/Assets.xcassets/hide_video_icon.imageset/hide_video_icon.png
new file mode 100644
index 00000000..40889f77
Binary files /dev/null and b/ios/Runner/Assets.xcassets/hide_video_icon.imageset/hide_video_icon.png differ
diff --git a/ios/Runner/Assets.xcassets/mic_mute.imageset/Contents.json b/ios/Runner/Assets.xcassets/mic_mute.imageset/Contents.json
new file mode 100644
index 00000000..2a0f4d2e
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/mic_mute.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "mic_mute.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/mic_mute.imageset/mic_mute.png b/ios/Runner/Assets.xcassets/mic_mute.imageset/mic_mute.png
new file mode 100644
index 00000000..266cb6c7
Binary files /dev/null and b/ios/Runner/Assets.xcassets/mic_mute.imageset/mic_mute.png differ
diff --git a/ios/Runner/Assets.xcassets/mic_unmute.imageset/Contents.json b/ios/Runner/Assets.xcassets/mic_unmute.imageset/Contents.json
new file mode 100644
index 00000000..8e85d01a
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/mic_unmute.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "Group 8020.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/mic_unmute.imageset/Group 8020.png b/ios/Runner/Assets.xcassets/mic_unmute.imageset/Group 8020.png
new file mode 100644
index 00000000..ef7617f7
Binary files /dev/null and b/ios/Runner/Assets.xcassets/mic_unmute.imageset/Group 8020.png differ
diff --git a/ios/Runner/Assets.xcassets/video_mute.imageset/Contents.json b/ios/Runner/Assets.xcassets/video_mute.imageset/Contents.json
new file mode 100644
index 00000000..4403d6ee
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/video_mute.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "video_mute.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/video_mute.imageset/video_mute.png b/ios/Runner/Assets.xcassets/video_mute.imageset/video_mute.png
new file mode 100644
index 00000000..d6ccbe7a
Binary files /dev/null and b/ios/Runner/Assets.xcassets/video_mute.imageset/video_mute.png differ
diff --git a/ios/Runner/Assets.xcassets/video_unmute.imageset/Contents.json b/ios/Runner/Assets.xcassets/video_unmute.imageset/Contents.json
new file mode 100644
index 00000000..51724501
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/video_unmute.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "Group 8022.png",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/video_unmute.imageset/Group 8022.png b/ios/Runner/Assets.xcassets/video_unmute.imageset/Group 8022.png
new file mode 100644
index 00000000..6fcbe750
Binary files /dev/null and b/ios/Runner/Assets.xcassets/video_unmute.imageset/Group 8022.png differ
diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard
index 73e18f76..2bdee5a2 100755
--- a/ios/Runner/Base.lproj/Main.storyboard
+++ b/ios/Runner/Base.lproj/Main.storyboard
@@ -1,296 +1,366 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
-
+
-
-
-
-
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
-
-
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Extensions.swift b/ios/Runner/Extensions.swift
new file mode 100644
index 00000000..b79c8deb
--- /dev/null
+++ b/ios/Runner/Extensions.swift
@@ -0,0 +1,27 @@
+//
+// Extensions.swift
+// Runner
+//
+// Created by Zohaib Iqbal Kambrani on 09/06/2021.
+// Copyright © 2021 The Chromium Authors. All rights reserved.
+//
+import AADraggableView
+
+extension AADraggableView{
+ func enable(_ enable:Bool){
+ isEnabled = enable
+ if enable == false{
+ gestureRecognizers?.forEach({ gest in
+ removeGestureRecognizer(gest)
+ })
+ }
+ }
+}
+
+extension UIView{
+ func hidden(_ hidden:Bool, rootView:UIView){
+ UIView.transition(with: rootView, duration: 0.5, options: .transitionCrossDissolve, animations: {
+ self.isHidden = hidden
+ })
+ }
+}
diff --git a/ios/Runner/MainAppViewController.swift b/ios/Runner/MainAppViewController.swift
new file mode 100644
index 00000000..c7b7a18d
--- /dev/null
+++ b/ios/Runner/MainAppViewController.swift
@@ -0,0 +1,190 @@
+//
+// MainAppViewController.swift
+// Runner
+//
+// Created by Zohaib Iqbal Kambrani on 08/06/2021.
+// Copyright © 2021 The Chromium Authors. All rights reserved.
+//
+
+import Foundation
+import AADraggableView
+
+class MainAppViewController: FlutterViewController{
+ var videoCallContainer:AADraggableView!
+ var videoCallViewController:VideoCallViewController!
+ var videoCallFlutterResult:FlutterResult?
+ var vdoCallViewFloatRectConstraint:[NSLayoutConstraint]!
+ var vdoCallViewFullConstraint:[NSLayoutConstraint]!
+ var vdoCallViewFloatCircleConstraint:[NSLayoutConstraint]!
+
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ initFlutterBridge()
+ prepareVideoCallView()
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ }
+
+ var videoCallChannel:FlutterMethodChannel?
+ private func initFlutterBridge(){
+ videoCallChannel = FlutterMethodChannel(name: "Dr.cloudSolution/videoCall", binaryMessenger: binaryMessenger)
+ videoCallChannel?.setMethodCallHandler({
+ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
+ switch call.method {
+ case "openVideoCall":
+ self.startVideoCall(result: result, call: call)
+ default:
+ result(FlutterMethodNotImplemented)
+ }
+ })
+ }
+
+}
+
+
+// Video Call Functions
+extension MainAppViewController : ICallProtocol{
+
+ func prepareVideoCallView(){
+ videoCallContainer = AADraggableView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height))
+ videoCallContainer.backgroundColor = UIColor.black
+ videoCallContainer.isHidden = true
+ videoCallContainer.clipsToBounds = true
+ videoCallContainer.padding = 20
+ videoCallContainer.reposition = .edgesOnly
+ videoCallContainer.isEnabled = false
+
+ view.addSubview(videoCallContainer)
+ setVideoViewConstrints()
+ NSLayoutConstraint.activate(vdoCallViewFullConstraint)
+ NSLayoutConstraint.deactivate(vdoCallViewFloatRectConstraint)
+
+ ViewEmbedder.embed(
+ withIdentifier: "videoCall", // Storyboard ID
+ parent: self,
+ container: self.videoCallContainer){ vc in
+ self.videoCallViewController = vc as? VideoCallViewController
+
+ }
+ }
+
+ private func showVideo(show:Bool){
+ self.videoCallContainer.hidden(!show, rootView: view)
+ }
+
+ private func startVideoCall(result: @escaping FlutterResult, call:FlutterMethodCall) {
+ videoCallFlutterResult = result
+
+ if let arguments = call.arguments as? NSDictionary{
+ showVideoCallView(true)
+
+ videoCallViewController.onRectFloat = { isRectFloat in
+ self.rectFloatVideoCallView(isRectFloat)
+ }
+
+ videoCallViewController.onCircleFloat = { isCircleFloat in
+ self.circleFloatVideoCallView(isCircleFloat)
+ }
+ videoCallViewController.onCallConnect = {
+ self.videoCallChannel?.invokeMethod("onCallConnected",arguments: nil)
+ }
+ videoCallViewController.onCallDisconnect = {
+ self.showVideoCallView(false)
+ self.videoCallViewController.minimizeVideoState(state: false)
+ self.videoCallChannel?.invokeMethod("onCallDisconnected",arguments: nil)
+ }
+ videoCallViewController.callBack = self
+ videoCallViewController.start(params: VideoCallRequestParameters(dictionary: arguments))
+ }
+
+
+ }
+
+ private func rectFloatVideoCallView(_ value:Bool){
+ videoCallContainer.enable(value)
+
+ UIView.animate(withDuration: 0.5) {
+ if(value){
+ NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
+ NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
+ NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint)
+ }else{
+ NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint)
+ NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
+ NSLayoutConstraint.activate(self.vdoCallViewFullConstraint)
+ }
+ self.videoCallContainer.layer.cornerRadius = value ? 10 : 0
+ self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil
+ self.videoCallContainer.layer.borderWidth = value ? 2 : 0
+ self.view.layoutIfNeeded()
+ }
+ }
+
+ private func circleFloatVideoCallView(_ value:Bool){
+ videoCallContainer.reposition = value ? .sticky : .edgesOnly
+
+ UIView.animate(withDuration: 0.5) {
+ if(value){
+ NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
+ NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint)
+ NSLayoutConstraint.activate(self.vdoCallViewFloatCircleConstraint)
+ self.videoCallContainer.layer.cornerRadius = 35
+ }else{
+ NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint)
+ NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
+ NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
+ self.videoCallContainer.layer.cornerRadius = 10
+
+ }
+ self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil
+ self.videoCallContainer.layer.borderWidth = value ? 2 : 0
+ self.view.layoutIfNeeded()
+ }
+ }
+
+ private func showVideoCallView(_ value:Bool){
+ self.videoCallContainer.hidden(!value, rootView: view)
+ }
+
+ func sessionDone(res: Any) {
+ videoCallFlutterResult?(res)
+ }
+
+ func sessionNotResponded(res: Any) {
+ videoCallFlutterResult?(res)
+ }
+
+
+ func setVideoViewConstrints(){
+ videoCallContainer.layer.shadowColor = UIColor.black.cgColor
+ videoCallContainer.layer.shadowOffset = CGSize(width: 1, height: 1)
+ videoCallContainer.layer.shadowRadius = 5
+
+ let screen = UIScreen.main.bounds
+
+ videoCallContainer.translatesAutoresizingMaskIntoConstraints = false
+
+ vdoCallViewFullConstraint = [
+ videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor),
+ videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+ videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width),
+ videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height)
+ ]
+ vdoCallViewFloatRectConstraint = [
+ videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40),
+ videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
+ videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width/3),
+ videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height/3.5)
+ ]
+ vdoCallViewFloatCircleConstraint = [
+ videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40),
+ videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
+ videoCallContainer.widthAnchor.constraint(equalToConstant: 70),
+ videoCallContainer.heightAnchor.constraint(equalToConstant: 70)
+ ]
+ }
+
+}
diff --git a/ios/Runner/VCEmbeder.swift b/ios/Runner/VCEmbeder.swift
new file mode 100644
index 00000000..9617a247
--- /dev/null
+++ b/ios/Runner/VCEmbeder.swift
@@ -0,0 +1,78 @@
+//
+// VCEmbeder.swift
+// Runner
+//
+// Created by Zohaib Iqbal Kambrani on 08/06/2021.
+// Copyright © 2021 The Chromium Authors. All rights reserved.
+//
+
+import Foundation
+
+extension UIView {
+ func fill(to parent: UIView, animateDuration:Double = 0.5) {
+ self.topAnchor.constraint(equalTo: parent.topAnchor).isActive = true
+ self.leadingAnchor.constraint(equalTo: parent.leadingAnchor).isActive = true
+ self.bottomAnchor.constraint(equalTo: parent.bottomAnchor).isActive = true
+ self.trailingAnchor.constraint(equalTo: parent.trailingAnchor).isActive = true
+ UIView.animate(withDuration: animateDuration) {
+ parent.layoutIfNeeded()
+ }
+ }
+
+ func fillToParent(animateDuration:Double = 0.5) {
+ if let parent = self.superview{
+ self.topAnchor.constraint(equalTo: parent.topAnchor).isActive = true
+ self.leadingAnchor.constraint(equalTo: parent.leadingAnchor).isActive = true
+ self.bottomAnchor.constraint(equalTo: parent.bottomAnchor).isActive = true
+ self.trailingAnchor.constraint(equalTo: parent.trailingAnchor).isActive = true
+ UIView.animate(withDuration: animateDuration) {
+ parent.layoutIfNeeded()
+ }
+ }
+ }
+
+ func fillInTo(view:UIView) {
+ view.addSubview(self)
+ fillToParent()
+ }
+}
+
+class ViewEmbedder {
+ class func embed(
+ parent:UIViewController,
+ container:UIView,
+ child:UIViewController,
+ previous:UIViewController?){
+
+ if let previous = previous {
+ removeFromParent(vc: previous)
+ }
+ child.willMove(toParent: parent)
+ parent.addChild(child)
+ container.addSubview(child.view)
+ child.didMove(toParent: parent)
+ let w = container.frame.size.width;
+ let h = container.frame.size.height;
+ child.view.frame = CGRect(x: 0, y: 0, width: w, height: h)
+ child.view.backgroundColor = UIColor.black
+
+ child.view.fill(to: container)
+ }
+
+ class func removeFromParent(vc:UIViewController){
+ vc.willMove(toParent: nil)
+ vc.view.removeFromSuperview()
+ vc.removeFromParent()
+ }
+
+ class func embed(withIdentifier id:String, parent:UIViewController, container:UIView, completion:((UIViewController)->Void)? = nil){
+ let vc = parent.storyboard!.instantiateViewController(withIdentifier: id)
+ embed(
+ parent: parent,
+ container: container,
+ child: vc,
+ previous: parent.children.first
+ )
+ completion?(vc)
+ }
+}
diff --git a/ios/Runner/VideoCallRequestParameters.swift b/ios/Runner/VideoCallRequestParameters.swift
new file mode 100644
index 00000000..543d7e8b
--- /dev/null
+++ b/ios/Runner/VideoCallRequestParameters.swift
@@ -0,0 +1,29 @@
+
+
+import Foundation
+
+class VideoCallRequestParameters{
+ var apiKey:String?
+ var sessionId:String?
+ var token:String?
+ var lang:String?
+ var vcId:Int?
+ var tokenId:String?
+ var generalId:String?
+ var doctorId:Int?
+ var baseUrl:String?
+ var patientName:String?
+
+ init(dictionary:NSDictionary){
+ self.apiKey = dictionary["kApiKey"] as? String
+ self.sessionId = dictionary["kSessionId"] as? String
+ self.token = dictionary["kToken"] as? String
+ self.lang = dictionary["appLang"] as? String
+ self.vcId = dictionary["VC_ID"] as? Int
+ self.tokenId = dictionary["TokenID"] as? String
+ self.generalId = dictionary["generalId"] as? String
+ self.doctorId = dictionary["DoctorId"] as? Int
+ self.baseUrl = dictionary["baseUrl"] as? String
+ self.patientName = dictionary["patientName"] as? String
+ }
+}
diff --git a/ios/Runner/VideoViewController.swift b/ios/Runner/VideoCallViewController.swift
similarity index 62%
rename from ios/Runner/VideoViewController.swift
rename to ios/Runner/VideoCallViewController.swift
index 44e45f3a..80a6fcb8 100644
--- a/ios/Runner/VideoViewController.swift
+++ b/ios/Runner/VideoCallViewController.swift
@@ -9,9 +9,9 @@
import UIKit
import OpenTok
import Alamofire
+import AADraggableView
-
-class ViewController: UIViewController {
+class VideoCallViewController: UIViewController {
var session: OTSession?
var publisher: OTPublisher?
@@ -31,21 +31,191 @@ class ViewController: UIViewController {
var callBack: ICallProtocol?
var timer = Timer()
- var seconds = 30
+ var seconds = 55
var isUserConnect : Bool = false
+ var onRectFloat:((Bool)->Void)? = nil
+ var onCircleFloat:((Bool)->Void)? = nil
+ var onCallConnect:(()->Void)? = nil
+ var onCallDisconnect:(()->Void)? = nil
+
+
+ @IBOutlet weak var lblRemoteUsername: UILabel!
+
+ // Bottom Actions
+ @IBOutlet weak var videoMuteBtn: UIButton!
+ @IBOutlet weak var micMuteBtn: UIButton!
+ @IBOutlet weak var camSwitchBtn: UIButton!
+
+ @IBOutlet var minimizeConstraint: [NSLayoutConstraint]!
+ @IBOutlet var maximisedConstraint: [NSLayoutConstraint]!
+
+ @IBOutlet weak var btnMinimize: UIButton!
+ @IBOutlet weak var hideVideoBtn: UIButton!
+ var localVideoDraggable:AADraggableView?
+ @IBOutlet weak var controlButtons: UIView!
+ @IBOutlet weak var remoteVideoMutedIndicator: UIImageView!
+ @IBOutlet weak var localVideoMutedBg: UIView!
+
+ @IBOutlet weak var btnScreenTap: UIButton!
+ @IBOutlet weak var localVideoContainer: UIView!
+ @IBOutlet weak var topBar: UIView!
+ @IBOutlet weak var lblCallDuration: UILabel!
+ @IBOutlet weak var fullVideoView: UIView!
+ @IBOutlet weak var smallVideoView: UIView!{
+ didSet{
+ smallVideoView.layer.borderColor = UIColor.white.cgColor
+ localVideoDraggable = smallVideoView?.superview as? AADraggableView
+ localVideoDraggable?.reposition = .edgesOnly
+ }
+ }
override func viewDidLoad() {
- super.viewDidLoad()
+ super.viewDidLoad()
+ localVideoDraggable?.respectedView = localVideoContainer
+ }
+
+ @objc func click(gesture:UIGestureRecognizer){
+ gesture.view?.removeFromSuperview()
+ }
+
+ @IBAction func btnOnScreenTapped(_ sender: Any) {
+ if(hideVideoBtn.isSelected){
+ circleFloatBtnTapped(hideVideoBtn)
+
+ }else if(btnMinimize.isSelected){
+ btnMinimizeTapped(btnMinimize)
+ }
+ }
+
+ @IBAction func btnSwipeVideoTapped(_ sender: Any) {
+// let smallVdoRender = smallVideoView.subviews.first
+// let fullVdoRender = fullVideoView.subviews.first
+// if let vdo = smallVdoRender{
+// fullVideoView.addSubview(vdo)
+// }
+// if let vdo = fullVdoRender{
+// smallVideoView.addSubview(vdo)
+// }
+//
+// layoutVideoRenderViews()
+ }
+
+ @IBAction func didClickMuteButton(_ sender: UIButton) {
+ sender.isSelected = !sender.isSelected
+ publisher!.publishAudio = !sender.isSelected
+ }
+
+ @IBAction func didClickSpeakerButton(_ sender: UIButton) {
+ sender.isSelected = !sender.isSelected
+ subscriber?.subscribeToAudio = !sender.isSelected
+ }
+
+ @IBAction func didClickVideoMuteButton(_ sender: UIButton) {
+ sender.isSelected = !sender.isSelected
+ if publisher!.publishVideo {
+ publisher!.publishVideo = false
+ } else {
+ publisher!.publishVideo = true
+ }
+ smallVideoView.isHidden = sender.isSelected
+ localVideoMutedBg.isHidden = !sender.isSelected
+
+ }
+
+
+ @IBAction func didClickSwitchCameraButton(_ sender: UIButton) {
+ sender.isSelected = !sender.isSelected
+ if sender.isSelected {
+ publisher!.cameraPosition = AVCaptureDevice.Position.front
+ } else {
+ publisher!.cameraPosition = AVCaptureDevice.Position.back
+ }
+ }
+
+ @IBAction func hangUp(_ sender: UIButton) {
+ callBack?.sessionDone(res:["callResponse":"CallEnd"])
+ sessionDisconnect()
+ }
+
+ @IBAction func circleFloatBtnTapped(_ sender: UIButton) {
+ sender.isSelected = !sender.isSelected
+ onCircleFloat?(sender.isSelected)
+ topBar.isHidden = sender.isSelected
+ controlButtons.isHidden = sender.isSelected
+ smallVideoView.isHidden = sender.isSelected
+ self.publisher?.view?.layoutIfNeeded()
+ }
+
+ @IBAction func btnMinimizeTapped(_ sender: UIButton) {
+ minimizeVideoState(state: !sender.isSelected)
+ btnScreenTap.isHidden = !sender.isSelected
+ }
+
+ func minimizeVideoState(state:Bool){
+ btnMinimize.isSelected = state
+ onRectFloat?(state)
- setupButtons()
- askForMicrophonePermission()
- requestCameraPermissionsIfNeeded()
- hideVideoMuted()
- setupSession()
-
- }
+ NSLayoutConstraint.activate(state ? minimizeConstraint : maximisedConstraint)
+ NSLayoutConstraint.deactivate(state ? maximisedConstraint : minimizeConstraint)
+ localVideoDraggable?.enable(!state)
+
+ lblRemoteUsername.isHidden = state
+ hideVideoBtn.isHidden = !state
+ lblCallDuration.superview?.isHidden = !hideVideoBtn.isHidden
+
+ UIView.animate(withDuration: 0.5) {
+ self.videoMuteBtn.isHidden = state
+ self.micMuteBtn.isHidden = state
+ self.camSwitchBtn.isHidden = state
+ self.layoutVideoRenderViews()
+ }
+ }
+ func layoutVideoRenderViews(){
+ if let publisherVdoSize = publisher?.view?.superview?.bounds.size{
+ publisher?.view?.frame = CGRect(x: 0, y: 0, width: publisherVdoSize.width, height: publisherVdoSize.height)
+ }
+ if let subscriberVdoSize = subscriber?.view?.superview?.bounds.size{
+ subscriber?.view?.frame = CGRect(x: 0, y: 0, width: subscriberVdoSize.width, height: subscriberVdoSize.height)
+ }
+ }
+
+ var durationTimer:Timer?;
+ func startUpdateCallDuration(){
+ var seconds = 0
+ durationTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
+ seconds = seconds+1
+ let durationSegments = (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
+ let hours = String(format: "%02d", durationSegments.0)
+ let mins = String(format: "%02d", durationSegments.1)
+ let secs = String(format: "%02d", durationSegments.2)
+ let durationString = "\(mins):\(secs)"
+
+ self.lblCallDuration.text = durationString
+ }
+ }
+
+ func start(params:VideoCallRequestParameters){
+ lblRemoteUsername.text = params.patientName ?? "- - -"
+ btnScreenTap.isHidden = true
+ hideVideoBtn.isHidden = true
+
+ self.kApiKey = params.apiKey ?? ""
+ self.kSessionId = params.sessionId ?? ""
+ self.kToken = params.token ?? ""
+ self.VC_ID = params.vcId ?? 0
+ self.generalid = params.generalId ?? ""
+ self.TokenID = params.tokenId ?? ""
+ self.DoctorId = params.doctorId ?? 0
+ self.baseUrl = params.baseUrl ?? ""
+
+ askForMicrophonePermission()
+ requestCameraPermissionsIfNeeded()
+ hideVideoMuted()
+ setupSession()
+
+ }
private func changeCallStatus(callStatus:Int){
let URL_USER_REGISTER = baseUrl+"LiveCareApi/DoctorApp/ChangeCallStatus"
@@ -107,13 +277,6 @@ class ViewController: UIViewController {
}
}
-
- func setupButtons() {
- perform(#selector(hideControlButtons), with: nil, afterDelay: 3)
- let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(remoteVideoTapped(_:)))
- view.addGestureRecognizer(tapGestureRecognizer)
- view.isUserInteractionEnabled = true
- }
// MARK: -Microphone Camera and Permission Request
func askForMicrophonePermission() {
@@ -137,59 +300,16 @@ class ViewController: UIViewController {
// display a useful message asking the user to grant permissions from within Settings > Privacy > Camera
}
-
- @IBAction func didClickMuteButton(_ sender: UIButton) {
- sender.isSelected = !sender.isSelected
- publisher!.publishAudio = !sender.isSelected
-
- }
-
- @IBAction func didClickSpeakerButton(_ sender: UIButton) {
- sender.isSelected = !sender.isSelected
- subscriber?.subscribeToAudio = !sender.isSelected
- // resetHideButtonsTimer()
- }
-
- @IBAction func didClickVideoMuteButton(_ sender: UIButton) {
- sender.isSelected = !sender.isSelected
- if publisher!.publishVideo {
- publisher!.publishVideo = false
- } else {
- publisher!.publishVideo = true
- }
- localVideo.isHidden = sender.isSelected
- localVideoMutedBg.isHidden = !sender.isSelected
- localVideoMutedIndicator.isHidden = !sender.isSelected
- // resetHideButtonsTimer()
-
- }
-
-
- @IBAction func didClickSwitchCameraButton(_ sender: UIButton) {
- sender.isSelected = !sender.isSelected
- if sender.isSelected {
- publisher!.cameraPosition = AVCaptureDevice.Position.front
- } else {
- publisher!.cameraPosition = AVCaptureDevice.Position.back
- }
- /// resetHideButtonsTimer()
- }
-
- @IBAction func hangUp(_ sender: UIButton) {
- callBack?.sessionDone(res:["callResponse":"CallEnd"])
- sessionDisconnect()
- }
-
-
func sessionDisconnect() {
changeCallStatus(callStatus: 16)
if (session != nil) {
print("disconnecting....")
session!.disconnect(nil)
dismiss(animated: true)
- return
}
dismiss(animated: true)
+ onCallDisconnect?()
+ durationTimer?.invalidate()
}
func requestCameraPermissionsIfNeeded() {
@@ -226,7 +346,6 @@ class ViewController: UIViewController {
func hideVideoMuted() {
remoteVideoMutedIndicator.isHidden = true
localVideoMutedBg.isHidden = true
- localVideoMutedIndicator.isHidden = true
}
func setupSession() {
@@ -267,19 +386,6 @@ class ViewController: UIViewController {
- @IBOutlet weak var localVideo: UIView!
-
- @IBOutlet weak var remoteVideo: UIView!
-
- @IBOutlet weak var controlButtons: UIView!
-
- @IBOutlet weak var remoteVideoMutedIndicator: UIImageView!
-
- @IBOutlet weak var localVideoMutedBg: UIImageView!
-
-
- @IBOutlet weak var localVideoMutedIndicator: UIImageView!
-
@objc func updateTimer(){
seconds -= 1 //This will decrement(count down)the seconds.
print(seconds)
@@ -293,17 +399,11 @@ class ViewController: UIViewController {
}
-extension ViewController: OTSessionDelegate {
+extension VideoCallViewController: OTSessionDelegate {
func sessionDidConnect(_ session: OTSession) {
- print("The client connected to the OpenTok session.")
-
-
-
-
- timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(ViewController.updateTimer)), userInfo: nil, repeats: true)
-
-
+ print("The client connected to the OpenTok session.")
+ timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(VideoCallViewController.updateTimer)), userInfo: nil, repeats: true)
setupPublisher()
}
@@ -318,10 +418,12 @@ extension ViewController: OTSessionDelegate {
if error != nil {
showAlert(error?.localizedDescription)
}
-
- publisher?.view!.frame = CGRect(x: localVideo.bounds.origin.x, y: localVideo.bounds.origin.y, width: localVideo.bounds.size.width, height: localVideo.bounds.size.height)
-
- localVideo.addSubview((publisher?.view)!)
+
+ publisher?.view?.tag = 11
+ publisher?.view?.layer.cornerRadius = 5
+ publisher?.view?.clipsToBounds = true
+ smallVideoView.addSubview((publisher?.view)!)
+ layoutVideoRenderViews()
}
func sessionDidDisconnect(_ session: OTSession) {
@@ -346,27 +448,27 @@ extension ViewController: OTSessionDelegate {
func session(_ session: OTSession, streamCreated stream: OTStream) {
- subscriber = OTSubscriber(stream: stream, delegate: self)
- guard let subscriber = subscriber else {
- return
- }
+ subscriber = OTSubscriber(stream: stream, delegate: self)
+ guard let subscriber = subscriber else {
+ return
+ }
- var error: OTError?
- session.subscribe(subscriber, error: &error)
- guard error == nil else {
- print(error!)
- return
- }
+ var error: OTError?
+ session.subscribe(subscriber, error: &error)
+ guard error == nil else {
+ print(error!)
+ return
+ }
- guard let subscriberView = subscriber.view else {
- return
- }
- subscriberView.frame = UIScreen.main.bounds
- view.insertSubview(subscriberView, at: 0)
+ guard let subscriberView = subscriber.view else {
+ return
+ }
+ subscriberView.tag = 22
+ fullVideoView.addSubview(subscriberView)
+ layoutVideoRenderViews()
-// if nil == subscriber {
-// setupSubscribe(stream)
-// }
+ startUpdateCallDuration()
+ onCallConnect?()
}
func setupSubscribe(_ stream: OTStream?) {
@@ -408,19 +510,13 @@ extension ViewController: OTSessionDelegate {
}
-extension ViewController: OTPublisherDelegate {
+extension VideoCallViewController: OTPublisherDelegate {
func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
print("The publisher failed: \(error)")
}
- @objc func remoteVideoTapped(_ recognizer: UITapGestureRecognizer?) {
- if controlButtons.isHidden {
- controlButtons.isHidden = false
- perform(#selector(hideControlButtons), with: nil, afterDelay: 3)
- }
- }
}
-extension ViewController: OTSubscriberDelegate {
+extension VideoCallViewController: OTSubscriberDelegate {
public func subscriberDidConnect(toStream subscriber: OTSubscriberKit) {
print("The subscriber did connect to the stream.")
}
@@ -428,8 +524,5 @@ extension ViewController: OTSubscriberDelegate {
public func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
print("The subscriber failed to connect to the stream.")
}
- @objc func hideControlButtons() {
- controlButtons.isHidden = true
- }
}
diff --git a/lib/client/base_app_client.dart b/lib/client/base_app_client.dart
index bba61c2a..00069e3a 100644
--- a/lib/client/base_app_client.dart
+++ b/lib/client/base_app_client.dart
@@ -3,6 +3,7 @@ import 'dart:io' show Platform;
import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
+import 'package:doctor_app_flutter/core/service/NavigationService.dart';
import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart';
import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart';
import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
@@ -12,6 +13,9 @@ import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'package:provider/provider.dart';
+import '../locator.dart';
+import '../routes.dart';
+
DrAppSharedPreferances sharedPref = new DrAppSharedPreferances();
Helpers helpers = new Helpers();
@@ -101,12 +105,13 @@ class BaseAppClient {
helpers.navigateToUpdatePage(parsed['ErrorEndUserMessage'], parsed['AndroidLink'], parsed['IOSLink']);
}
- if (!parsed['IsAuthenticated']) {
+ if (parsed['IsAuthenticated'] != null && !parsed['IsAuthenticated']) {
if (body['OTP_SendType'] != null) {
onFailure(getError(parsed), statusCode);
} else if (!isAllowAny) {
await Provider.of(AppGlobal.CONTEX, listen: false).logout();
Helpers.showErrorToast('Your session expired Please login again');
+ locator().pushNamedAndRemoveUntil(ROOT);
}
if (isAllowAny) {
onFailure(getError(parsed), statusCode);
diff --git a/lib/config/config.dart b/lib/config/config.dart
index 0283577e..eb361798 100644
--- a/lib/config/config.dart
+++ b/lib/config/config.dart
@@ -56,6 +56,8 @@ const ADD_REFERRED_DOCTOR_REMARKS = 'Services/DoctorApplication.svc/REST/AddRefe
const GET_MY_REFERRED_PATIENT = 'Services/DoctorApplication.svc/REST/GtMyReferredPatient';
+const GET_MY_REFERRED_OUT_PATIENT = 'Services/DoctorApplication.svc/REST/GtMyReferredOutPatient';
+
const GET_PENDING_REFERRAL_PATIENT = 'Services/DoctorApplication.svc/REST/PendingReferrals';
const CREATE_REFERRAL_PATIENT = 'Services/DoctorApplication.svc/REST/CreateReferral';
@@ -89,6 +91,8 @@ const CHECK_ACTIVATION_CODE_FOR_DOCTOR_APP = 'Services/DoctorApplication.svc/RES
const GET_DOC_PROFILES = 'Services/Doctors.svc/REST/GetDocProfiles';
const TRANSFERT_TO_ADMIN = 'LiveCareApi/DoctorApp/TransferToAdmin';
+const SEND_SMS_INSTRUCTIONS = 'LiveCareApi/DoctorApp/SendSMSInstruction';
+const GET_ALTERNATIVE_SERVICE = 'LiveCareApi/DoctorApp/GetAlternativeServices';
const END_CALL = 'LiveCareApi/DoctorApp/EndCall';
const END_CALL_WITH_CHARGE = 'LiveCareApi/DoctorApp/CompleteCallWithCharge';
const GET_DASHBOARD = 'Services/DoctorApplication.svc/REST/GetDoctorDashboardKPI';
@@ -177,6 +181,8 @@ const GET_ECG = "Services/Patients.svc/REST/HIS_GetPatientMuseResults";
const GET_MY_REFERRAL_INPATIENT = "Services/DoctorApplication.svc/REST/GtMyReferralPatient";
+const GET_MY_REFERRAL_OUT_PATIENT = "Services/DoctorApplication.svc/REST/GtMyReferralForOutPatient";
+
const GET_MY_DISCHARGE_PATIENT = "Services/DoctorApplication.svc/REST/GtMyDischargeReferralPatient";
const GET_DISCHARGE_PATIENT = "Services/DoctorApplication.svc/REST/GtMyDischargePatient";
@@ -217,6 +223,11 @@ const GET_PENDING_PATIENT_ER_FOR_DOCTOR_APP = 'Services/DoctorApplication.svc/RE
const DOCTOR_CHECK_HAS_LIVE_CARE = "Services/DoctorApplication.svc/REST/CheckDoctorHasLiveCare";
+const LIVE_CARE_IS_LOGIN = "LiveCareApi/DoctorApp/UseIsLogin";
+const ADD_REFERRED_REMARKS_NEW = "Services/DoctorApplication.svc/REST/AddReferredDoctorRemarks_New";
+const GET_SPECIAL_CLINICAL_CARE_LIST = "Services/DoctorApplication.svc/REST/GetSpecialClinicalCareList";
+const GET_SPECIAL_CLINICAL_CARE_MAPPING_LIST = "Services/DoctorApplication.svc/REST/GetSpecialClinicalCareMappingList";
+
var selectedPatientType = 1;
//*********change value to decode json from Dropdown ************
diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart
index 231e7f9b..270907be 100644
--- a/lib/config/localized_values.dart
+++ b/lib/config/localized_values.dart
@@ -568,7 +568,7 @@ const Map> localizedValues = {
'ar': "ليس هناك شكوى رئيس"
},
"more-verify": {
- "en": "More Verification Options",
+ "en": "More Verification \n Options",
"ar": "المزيد من خيارات التحقق"
},
"welcome-back": {"en": "Welcome back!", "ar": "مرحبا بعودتك!"},
@@ -651,6 +651,10 @@ const Map> localizedValues = {
'en': "add Selected Procedures",
'ar': "اضافة العمليات المختارة "
},
+ 'addProcedures': {
+ 'en': "Add Procedure",
+ 'ar': "اضافة العمليات"
+ },
'updateProcedure': {'en': "Update Procedure", 'ar': "تحديث العملية"},
'orderProcedure': {'en': "order procedure", 'ar': "طلب العمليات"},
'nameOrICD': {'en': "Name or ICD", 'ar': "الاسم او ICD"},
@@ -708,7 +712,7 @@ const Map> localizedValues = {
'days': {'en': "Days", 'ar': "أيام"},
'months': {'en': "Months", 'ar': "أشهر"},
'years': {'en': "Years", 'ar': "سنين"},
- 'hr': {'en': "HR", 'ar': "س"},
+ 'hr': {'en': "Hr", 'ar': "س"},
'min': {'en': "Min", 'ar': "د"},
'appointmentNumber': {'en': "Appointment Number", 'ar': "رقم الموعد"},
'referralStatusHold': {'en': "Hold", 'ar': "معلق"},
@@ -998,4 +1002,12 @@ const Map> localizedValues = {
"onHold": {"en": "On Hold", "ar": "قيد الانتظار"},
"verified": {"en": "Verified", "ar": "تم التحقق"},
"endCall": {"en": "End Call", "ar": "انهاء"},
+ "favoriteTemplates": {"en": "Favorite Templates", "ar": "القوالب المفضلة"},
+ "allProcedures": {"en": "All Procedures", "ar": "جميع الإجراءات"},
+ "allRadiology": {"en": "All Radiology", "ar": "جميع الأشعة"},
+ "allLab": {"en": "All Lab", "ar": "جميع المختبرات"},
+ "allPrescription": {"en": "All Prescription", "ar": "جميع الوصفات"},
+ "addPrescription": {"en": "Add prescription", "ar": "إضافة الوصفات"},
+ "edit": {"en": "Edit", "ar": "تعديل"},
+ "summeryReply": {"en": "Summary Reply", "ar": "موجز الرد"},
};
diff --git a/lib/config/size_config.dart b/lib/config/size_config.dart
index e4b1e745..8a9c7ac6 100644
--- a/lib/config/size_config.dart
+++ b/lib/config/size_config.dart
@@ -17,6 +17,11 @@ class SizeConfig {
static bool isPortrait = true;
static bool isMobilePortrait = false;
static bool isMobile = false;
+ static bool isHeightShort = false;
+ static bool isHeightVeryShort = false;
+ static bool isHeightMiddle = false;
+ static bool isHeightLarge = false;
+ static bool isWidthLarge = false;
void init(BoxConstraints constraints, Orientation orientation) {
realScreenHeight = constraints.maxHeight;
@@ -25,20 +30,30 @@ class SizeConfig {
if (constraints.maxWidth <= MAX_SMALL_SCREEN) {
isMobile = true;
}
+ if (constraints.maxHeight < 600) {
+ isHeightVeryShort = true;
+ } else if (constraints.maxHeight < 800) {
+ isHeightShort = true;
+ } else if (constraints.maxHeight < 1000) {
+ isHeightMiddle = true;
+ } else {
+ isHeightLarge = true;
+ }
+
+ if(constraints.maxWidth > 600) {
+ isWidthLarge = true;
+ }
+
if (orientation == Orientation.portrait) {
isPortrait = true;
if (realScreenWidth! < 450) {
isMobilePortrait = true;
}
- // textMultiplier = _blockHeight;
- // imageSizeMultiplier = _blockWidth;
screenHeight = realScreenHeight;
screenWidth = realScreenWidth;
} else {
isPortrait = false;
isMobilePortrait = false;
- // textMultiplier = _blockWidth;
- // imageSizeMultiplier = _blockHeight;
screenHeight = realScreenWidth;
screenWidth = realScreenHeight;
}
@@ -59,4 +74,29 @@ class SizeConfig {
print('isPortrait $isPortrait');
print('isMobilePortrait $isMobilePortrait');
}
+
+ static getTextMultiplierBasedOnWidth({double width}){
+ // TODO handel LandScape case
+ if(width != null) {
+ return width / 100;
+ }
+ return widthMultiplier;
+ }
+
+
+ static getWidthMultiplier({double width}){
+ // TODO handel LandScape case
+ if(width != null) {
+ return width / 100;
+ }
+ return widthMultiplier;
+ }
+
+ static getHeightMultiplier({double height}){
+ // TODO handel LandScape case
+ if(height != null) {
+ return height / 100;
+ }
+ return heightMultiplier;
+ }
}
diff --git a/lib/core/enum/PatientType.dart b/lib/core/enum/PatientType.dart
new file mode 100644
index 00000000..96fd9ae5
--- /dev/null
+++ b/lib/core/enum/PatientType.dart
@@ -0,0 +1,4 @@
+enum PatientType{
+ IN_PATIENT,
+ OUT_PATIENT,
+}
\ No newline at end of file
diff --git a/lib/core/model/live_care/AlternativeServicesList.dart b/lib/core/model/live_care/AlternativeServicesList.dart
new file mode 100644
index 00000000..11f27b95
--- /dev/null
+++ b/lib/core/model/live_care/AlternativeServicesList.dart
@@ -0,0 +1,43 @@
+import 'package:flutter/material.dart';
+
+class AlternativeService {
+ int serviceID;
+ String serviceName;
+ bool isSelected;
+
+ AlternativeService(
+ {this.serviceID, this.serviceName, this.isSelected = false});
+
+ AlternativeService.fromJson(Map json) {
+ serviceID = json['ServicID'];
+ serviceName = json['ServiceName'];
+ isSelected = false;
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ServicID'] = this.serviceID;
+ data['ServiceName'] = this.serviceName;
+ return data;
+ }
+}
+
+class AlternativeServicesList with ChangeNotifier {
+ List _alternativeServicesList;
+
+ getServicesList(){
+ return _alternativeServicesList;
+ }
+
+ setServicesList(List alternativeServicesList) {
+ this._alternativeServicesList = alternativeServicesList;
+ notifyListeners();
+ }
+
+ setSelected(AlternativeService service, bool isSelected) {
+ List alternativeService = _alternativeServicesList.where((element) => service.serviceID == element.serviceID).toList();
+
+ alternativeService[0].isSelected = isSelected;
+ notifyListeners();
+ }
+}
diff --git a/lib/core/model/live_care/live_care_login_reguest_model.dart b/lib/core/model/live_care/live_care_login_reguest_model.dart
new file mode 100644
index 00000000..e14d4223
--- /dev/null
+++ b/lib/core/model/live_care/live_care_login_reguest_model.dart
@@ -0,0 +1,27 @@
+class LiveCareUserLoginRequestModel {
+ String tokenID;
+ String generalid;
+ int doctorId;
+ int isOutKsa;
+ int isLogin;
+
+ LiveCareUserLoginRequestModel({this.tokenID, this.generalid, this.doctorId, this.isOutKsa, this.isLogin});
+
+ LiveCareUserLoginRequestModel.fromJson(Map json) {
+ tokenID = json['TokenID'];
+ generalid = json['generalid'];
+ doctorId = json['DoctorId'];
+ isOutKsa = json['IsOutKsa'];
+ isLogin = json['IsLogin'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['TokenID'] = this.tokenID;
+ data['generalid'] = this.generalid;
+ data['DoctorId'] = this.doctorId;
+ data['IsOutKsa'] = this.isOutKsa;
+ data['IsLogin'] = this.isLogin;
+ return data;
+ }
+}
diff --git a/lib/core/model/patient_muse/PatientSearchRequestModel.dart b/lib/core/model/patient_muse/PatientSearchRequestModel.dart
index 3a722c96..7117382c 100644
--- a/lib/core/model/patient_muse/PatientSearchRequestModel.dart
+++ b/lib/core/model/patient_muse/PatientSearchRequestModel.dart
@@ -11,20 +11,24 @@ class PatientSearchRequestModel {
int ?searchType;
String? mobileNo;
String? identificationNo;
+ int nursingStationID;
+ int clinicID=0;
PatientSearchRequestModel(
- {this.doctorID =0,
- this.firstName ="0",
- this.middleName ="0",
- this.lastName ="0",
- this.patientMobileNumber ="0",
- this.patientIdentificationID ="0",
- this.patientID =0,
- this.searchType =1,
- this.mobileNo="",
- this.identificationNo="0",
- this.from ="0",
- this.to ="0"});
+ {this.doctorID = 0,
+ this.firstName = "0",
+ this.middleName = "0",
+ this.lastName = "0",
+ this.patientMobileNumber = "0",
+ this.patientIdentificationID = "0",
+ this.patientID = 0,
+ this.searchType = 1,
+ this.mobileNo = "",
+ this.identificationNo = "0",
+ this.from = "0",
+ this.to = "0",
+ this.clinicID,
+ this.nursingStationID = 0});
PatientSearchRequestModel.fromJson(Map json) {
doctorID = json['DoctorID'];
@@ -39,6 +43,8 @@ class PatientSearchRequestModel {
searchType = json['SearchType'];
mobileNo = json['MobileNo'];
identificationNo = json['IdentificationNo'];
+ nursingStationID = json['NursingStationID'];
+ clinicID = json['ClinicID'];
}
Map toJson() {
@@ -55,6 +61,9 @@ class PatientSearchRequestModel {
data['SearchType'] = this.searchType;
data['MobileNo'] = this.mobileNo;
data['IdentificationNo'] = this.identificationNo;
+ data['NursingStationID'] = this.nursingStationID;
+ data['ClinicID'] = this.clinicID;
+ data['ProjectID'] = 0;
return data;
}
}
diff --git a/lib/core/model/referral/MyReferralPatientModel.dart b/lib/core/model/referral/MyReferralPatientModel.dart
index 87757148..ec1f7758 100644
--- a/lib/core/model/referral/MyReferralPatientModel.dart
+++ b/lib/core/model/referral/MyReferralPatientModel.dart
@@ -61,71 +61,74 @@ class MyReferralPatientModel {
String? priorityDescription;
String? referringClinicDescription;
String? referringDoctorName;
+ int referalStatus;
MyReferralPatientModel(
{this.rowID,
- this.projectID,
- this.lineItemNo,
- this.doctorID,
- this.patientID,
- this.doctorName,
- this.doctorNameN,
- this.firstName,
- this.middleName,
- this.lastName,
- this.firstNameN,
- this.middleNameN,
- this.lastNameN,
- this.gender,
- this.dateofBirth,
- this.mobileNumber,
- this.emailAddress,
- this.patientIdentificationNo,
- this.patientType,
- this.admissionNo,
- this.admissionDate,
- this.roomID,
- this.bedID,
- this.nursingStationID,
- this.description,
- this.nationalityName,
- this.nationalityNameN,
- this.clinicDescription,
- this.clinicDescriptionN,
- this.referralDoctor,
- this.referringDoctor,
- this.referralClinic,
- this.referringClinic,
- this.referralStatus,
- this.referralDate,
- this.referringDoctorRemarks,
- this.referredDoctorRemarks,
- this.referralResponseOn,
- this.priority,
- this.frequency,
- this.mAXResponseTime,
- this.episodeID,
- this.appointmentNo,
- this.appointmentDate,
- this.appointmentType,
- this.patientMRN,
- this.createdOn,
- this.clinicID,
- this.nationalityID,
- this.age,
- this.doctorImageURL,
- this.frequencyDescription,
- this.genderDescription,
- this.isDoctorLate,
- this.isDoctorResponse,
- this.nationalityFlagURL,
- this.nursingStationName,
- this.priorityDescription,
- this.referringClinicDescription,
- this.referringDoctorName});
+ this.projectID,
+ this.lineItemNo,
+ this.doctorID,
+ this.patientID,
+ this.doctorName,
+ this.doctorNameN,
+ this.firstName,
+ this.middleName,
+ this.lastName,
+ this.firstNameN,
+ this.middleNameN,
+ this.lastNameN,
+ this.gender,
+ this.dateofBirth,
+ this.mobileNumber,
+ this.emailAddress,
+ this.patientIdentificationNo,
+ this.patientType,
+ this.admissionNo,
+ this.admissionDate,
+ this.roomID,
+ this.bedID,
+ this.nursingStationID,
+ this.description,
+ this.nationalityName,
+ this.nationalityNameN,
+ this.clinicDescription,
+ this.clinicDescriptionN,
+ this.referralDoctor,
+ this.referringDoctor,
+ this.referralClinic,
+ this.referringClinic,
+ this.referralStatus,
+ this.referralDate,
+ this.referringDoctorRemarks,
+ this.referredDoctorRemarks,
+ this.referralResponseOn,
+ this.priority,
+ this.frequency,
+ this.mAXResponseTime,
+ this.episodeID,
+ this.appointmentNo,
+ this.appointmentDate,
+ this.appointmentType,
+ this.patientMRN,
+ this.createdOn,
+ this.clinicID,
+ this.nationalityID,
+ this.age,
+ this.doctorImageURL,
+ this.frequencyDescription,
+ this.genderDescription,
+ this.isDoctorLate,
+ this.isDoctorResponse,
+ this.nationalityFlagURL,
+ this.nursingStationName,
+ this.priorityDescription,
+ this.referringClinicDescription,
+ this.referringDoctorName,
+ this.referalStatus});
MyReferralPatientModel.fromJson(Map json) {
rowID = json['RowID'];
+ referalStatus = json['ReferalStatus'];
projectID = json['ProjectID'];
lineItemNo = json['LineItemNo'];
doctorID = json['DoctorID'];
@@ -158,8 +161,21 @@ class MyReferralPatientModel {
referringDoctor = json['ReferringDoctor'];
referralClinic = json['ReferralClinic'];
referringClinic = json['ReferringClinic'];
- referralStatus = json['ReferralStatus'];
- referralDate = AppDateUtils.convertStringToDate(json['ReferralDate']);
+ referralStatus = json["ReferralStatus"] is String
+ ? json['ReferralStatus'] == "Accepted"
+ ? 46
+ : json['ReferralStatus'] == "Pending"
+ ? 1
+ : 0
+ : json["ReferralStatus"];
+ try {
+ referralDate = AppDateUtils.getDateTimeFromString(json['ReferralDate']);
+ } catch (e) {
+ referralDate = AppDateUtils.convertStringToDate(json['ReferralDate']);
+ } finally {
+ referralDate = DateTime.now();
+ }
+
referringDoctorRemarks = json['ReferringDoctorRemarks'];
referredDoctorRemarks = json['ReferredDoctorRemarks'];
referralResponseOn = json['ReferralResponseOn'];
@@ -190,6 +206,7 @@ class MyReferralPatientModel {
Map toJson() {
final Map data = new Map();
data['RowID'] = this.rowID;
+ data['ReferalStatus'] = this.referalStatus;
data['ProjectID'] = this.projectID;
data['LineItemNo'] = this.lineItemNo;
data['DoctorID'] = this.doctorID;
@@ -253,6 +270,6 @@ class MyReferralPatientModel {
}
get patientName {
- return this.firstName!+" "+this.lastName!;
+ return this.firstName !+ " " + this.lastName!;
}
}
diff --git a/lib/core/model/referral/MyReferralPatientRequestModel.dart b/lib/core/model/referral/MyReferralPatientRequestModel.dart
new file mode 100644
index 00000000..08b98a99
--- /dev/null
+++ b/lib/core/model/referral/MyReferralPatientRequestModel.dart
@@ -0,0 +1,104 @@
+class MyReferralPatientRequestModel {
+ int channel;
+ int clinicID;
+ int doctorID;
+ int editedBy;
+ String firstName;
+ String from;
+ String iPAdress;
+ bool isLoginForDoctorApp;
+ int languageID;
+ String lastName;
+ String middleName;
+ int patientID;
+ String patientIdentificationID;
+ String patientMobileNumber;
+ bool patientOutSA;
+ int patientTypeID;
+ int projectID;
+ String sessionID;
+ String stamp;
+ String to;
+ String tokenID;
+ double versionID;
+ String vidaAuthTokenID;
+
+ MyReferralPatientRequestModel(
+ {this.channel,
+ this.clinicID,
+ this.doctorID,
+ this.editedBy,
+ this.firstName,
+ this.from,
+ this.iPAdress,
+ this.isLoginForDoctorApp,
+ this.languageID,
+ this.lastName,
+ this.middleName,
+ this.patientID,
+ this.patientIdentificationID,
+ this.patientMobileNumber,
+ this.patientOutSA,
+ this.patientTypeID,
+ this.projectID,
+ this.sessionID,
+ this.stamp,
+ this.to,
+ this.tokenID,
+ this.versionID,
+ this.vidaAuthTokenID});
+
+ MyReferralPatientRequestModel.fromJson(Map json) {
+ channel = json['Channel'];
+ clinicID = json['ClinicID'];
+ doctorID = json['DoctorID'];
+ editedBy = json['EditedBy'];
+ firstName = json['FirstName'];
+ from = json['From'];
+ iPAdress = json['IPAdress'];
+ isLoginForDoctorApp = json['IsLoginForDoctorApp'];
+ languageID = json['LanguageID'];
+ lastName = json['LastName'];
+ middleName = json['MiddleName'];
+ patientID = json['PatientID'];
+ patientIdentificationID = json['PatientIdentificationID'];
+ patientMobileNumber = json['PatientMobileNumber'];
+ patientOutSA = json['PatientOutSA'];
+ patientTypeID = json['PatientTypeID'];
+ projectID = json['ProjectID'];
+ sessionID = json['SessionID'];
+ stamp = json['stamp'];
+ to = json['To'];
+ tokenID = json['TokenID'];
+ versionID = json['VersionID'];
+ vidaAuthTokenID = json['VidaAuthTokenID'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['Channel'] = this.channel;
+ data['ClinicID'] = this.clinicID;
+ data['DoctorID'] = this.doctorID;
+ data['EditedBy'] = this.editedBy;
+ data['FirstName'] = this.firstName;
+ data['From'] = this.from;
+ data['IPAdress'] = this.iPAdress;
+ data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
+ data['LanguageID'] = this.languageID;
+ data['LastName'] = this.lastName;
+ data['MiddleName'] = this.middleName;
+ data['PatientID'] = this.patientID;
+ data['PatientIdentificationID'] = this.patientIdentificationID;
+ data['PatientMobileNumber'] = this.patientMobileNumber;
+ data['PatientOutSA'] = this.patientOutSA;
+ data['PatientTypeID'] = this.patientTypeID;
+ data['ProjectID'] = this.projectID;
+ data['SessionID'] = this.sessionID;
+ data['stamp'] = this.stamp;
+ data['To'] = this.to;
+ data['TokenID'] = this.tokenID;
+ data['VersionID'] = this.versionID;
+ data['VidaAuthTokenID'] = this.vidaAuthTokenID;
+ return data;
+ }
+}
diff --git a/lib/core/model/referral/add_referred_remarks_request.dart b/lib/core/model/referral/add_referred_remarks_request.dart
new file mode 100644
index 00000000..14089513
--- /dev/null
+++ b/lib/core/model/referral/add_referred_remarks_request.dart
@@ -0,0 +1,72 @@
+class AddReferredRemarksRequestModel {
+ int projectID;
+ int admissionNo;
+ int lineItemNo;
+ String referredDoctorRemarks;
+ int editedBy;
+ int referalStatus;
+ bool isLoginForDoctorApp;
+ String iPAdress;
+ bool patientOutSA;
+ String tokenID;
+ int languageID;
+ double versionID;
+ int channel;
+ String sessionID;
+ int deviceTypeID;
+
+ AddReferredRemarksRequestModel(
+ {this.projectID,
+ this.admissionNo,
+ this.lineItemNo,
+ this.referredDoctorRemarks,
+ this.editedBy,
+ this.referalStatus,
+ this.isLoginForDoctorApp,
+ this.iPAdress,
+ this.patientOutSA,
+ this.tokenID,
+ this.languageID,
+ this.versionID,
+ this.channel,
+ this.sessionID,
+ this.deviceTypeID});
+
+ AddReferredRemarksRequestModel.fromJson(Map json) {
+ projectID = json['ProjectID'];
+ admissionNo = json['AdmissionNo'];
+ lineItemNo = json['LineItemNo'];
+ referredDoctorRemarks = json['ReferredDoctorRemarks'];
+ editedBy = json['EditedBy'];
+ referalStatus = json['ReferalStatus'];
+ isLoginForDoctorApp = json['IsLoginForDoctorApp'];
+ iPAdress = json['IPAdress'];
+ patientOutSA = json['PatientOutSA'];
+ tokenID = json['TokenID'];
+ languageID = json['LanguageID'];
+ versionID = json['VersionID'];
+ channel = json['Channel'];
+ sessionID = json['SessionID'];
+ deviceTypeID = json['DeviceTypeID'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ProjectID'] = this.projectID;
+ data['AdmissionNo'] = this.admissionNo;
+ data['LineItemNo'] = this.lineItemNo;
+ data['ReferredDoctorRemarks'] = this.referredDoctorRemarks;
+ data['EditedBy'] = this.editedBy;
+ data['ReferalStatus'] = this.referalStatus;
+ data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
+ data['IPAdress'] = this.iPAdress;
+ data['PatientOutSA'] = this.patientOutSA;
+ data['TokenID'] = this.tokenID;
+ data['LanguageID'] = this.languageID;
+ data['VersionID'] = this.versionID;
+ data['Channel'] = this.channel;
+ data['SessionID'] = this.sessionID;
+ data['DeviceTypeID'] = this.deviceTypeID;
+ return data;
+ }
+}
diff --git a/lib/core/service/NavigationService.dart b/lib/core/service/NavigationService.dart
new file mode 100644
index 00000000..26191ffc
--- /dev/null
+++ b/lib/core/service/NavigationService.dart
@@ -0,0 +1,18 @@
+import 'package:flutter/material.dart';
+
+class NavigationService {
+ final GlobalKey navigatorKey =
+ new GlobalKey();
+ Future navigateTo(String routeName,{Object arguments}) {
+ return navigatorKey.currentState.pushNamed(routeName,arguments: arguments);
+ }
+
+ Future pushReplacementNamed(String routeName,{Object arguments}) {
+ return navigatorKey.currentState.pushReplacementNamed(routeName,arguments: arguments);
+ }
+
+
+ Future pushNamedAndRemoveUntil(String routeName) {
+ return navigatorKey.currentState.pushNamedAndRemoveUntil(routeName,(asd)=>false);
+ }
+}
\ No newline at end of file
diff --git a/lib/core/service/VideoCallService.dart b/lib/core/service/VideoCallService.dart
new file mode 100644
index 00000000..f72544a0
--- /dev/null
+++ b/lib/core/service/VideoCallService.dart
@@ -0,0 +1,89 @@
+import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
+import 'package:doctor_app_flutter/core/service/base/base_service.dart';
+import 'package:doctor_app_flutter/core/service/patient/LiveCarePatientServices.dart';
+import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart';
+import 'package:doctor_app_flutter/models/livecare/end_call_req.dart';
+import 'package:doctor_app_flutter/models/livecare/session_status_model.dart';
+import 'package:doctor_app_flutter/models/livecare/start_call_res.dart';
+import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
+import 'package:doctor_app_flutter/util/VideoChannel.dart';
+import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart';
+import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart';
+import 'package:flutter/cupertino.dart';
+
+import '../../locator.dart';
+import '../../routes.dart';
+import 'NavigationService.dart';
+
+class VideoCallService extends BaseService{
+
+ StartCallRes startCallRes;
+ PatiantInformtion patient;
+ LiveCarePatientServices _liveCarePatientServices = locator();
+
+ openVideo(StartCallRes startModel,PatiantInformtion patientModel,VoidCallback onCallConnected, VoidCallback onCallDisconnected)async{
+ this.startCallRes = startModel;
+ this.patient = patientModel;
+ DoctorProfileModel doctorProfile = await getDoctorProfile(isGetProfile: true);
+ await VideoChannel.openVideoCallScreen(
+ kToken: startCallRes.openTokenID,//"T1==cGFydG5lcl9pZD00NzI0Nzk1NCZzaWc9NGIyZDljOTY3YjFiNWU1YzUzNzFmMjIyNjJmNmEzY2Y5NzZjOTdlYzpzZXNzaW9uX2lkPTFfTVg0ME56STBOemsxTkg1LU1UWXlNekEyTlRRMU9EVXhObjVrVFRoMFlVdFJXaXRYTWpadFZGZHFhSGxZVGpOdE1UVi1mZyZjcmVhdGVfdGltZT0xNjIzMDY1NDk1Jm5vbmNlPTAuMjM2Mjk0NTIwMTkyOTA4OTcmcm9sZT1wdWJsaXNoZXImZXhwaXJlX3RpbWU9MTYyNTY1NzQ5NCZpbml0aWFsX2xheW91dF9jbGFzc19saXN0PQ==",
+ kSessionId:startCallRes.openSessionID,//1_MX40NzI0Nzk1NH5-MTYyMzA2NTQ1ODUxNn5kTTh0YUtRWitXMjZtVFdqaHlYTjNtMTV-fg
+ kApiKey: '46209962',//'47247954'
+ vcId: patient.vcId,
+ patientName: patient.fullName ?? (patient.firstName != null ? "${patient.firstName} ${patient.lastName}" : "-"),
+ tokenID: await sharedPref.getString(TOKEN),
+ generalId: GENERAL_ID,
+ doctorId: doctorProfile.doctorID,
+ onFailure: (String error) {
+ DrAppToastMsg.showErrorToast(error);
+ },onCallConnected: onCallConnected,
+ onCallEnd: () {
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ GifLoaderDialogUtils.showMyDialog(locator().navigatorKey.currentContext);
+ endCall(patient.vcId, false,).then((value) {
+ GifLoaderDialogUtils.hideDialog(locator().navigatorKey.currentContext);
+ if (hasError) {
+ DrAppToastMsg.showErrorToast(error);
+ }else
+ locator().navigateTo(PATIENTS_END_Call,arguments: {
+ "patient": patient,
+ });
+
+ });
+ });
+ },
+ onCallNotRespond: (SessionStatusModel sessionStatusModel) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ GifLoaderDialogUtils.showMyDialog(locator().navigatorKey.currentContext);
+ endCall(patient.vcId, sessionStatusModel.sessionStatus == 3,).then((value) {
+ GifLoaderDialogUtils.hideDialog(locator().navigatorKey.currentContext);
+ if (hasError) {
+ DrAppToastMsg.showErrorToast(error);
+ } else {
+ locator().navigateTo(PATIENTS_END_Call,arguments: {
+ "patient": patient,
+ });
+ }
+
+ });
+
+ });
+ });
+
+ }
+ Future endCall(int vCID, bool isPatient) async {
+ hasError = false;
+ await getDoctorProfile(isGetProfile: true);
+ EndCallReq endCallReq = new EndCallReq();
+ endCallReq.doctorId = doctorProfile.doctorID;
+ endCallReq.generalid = 'Cs2020@2016\$2958';
+ endCallReq.vCID = vCID;
+ endCallReq.isDestroy = isPatient;
+ await _liveCarePatientServices.endCall(endCallReq);
+ if (_liveCarePatientServices.hasError) {
+ error = _liveCarePatientServices.error;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/lib/core/service/home/dasboard_service.dart b/lib/core/service/home/dasboard_service.dart
index 401ec76e..5516923a 100644
--- a/lib/core/service/home/dasboard_service.dart
+++ b/lib/core/service/home/dasboard_service.dart
@@ -1,10 +1,12 @@
import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/core/service/base/base_service.dart';
import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
+import 'package:doctor_app_flutter/models/dashboard/get_special_clinical_care_List_Respose_Model.dart';
class DashboardService extends BaseService {
List _dashboardItemsList = [];
List get dashboardItemsList => _dashboardItemsList;
+
bool hasVirtualClinic = false;
String ?sServiceID;
@@ -24,8 +26,6 @@ class DashboardService extends BaseService {
super.error = error;
},
body: {
- // "VidaAuthTokenID":
- // "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIyODA0IiwianRpIjoiZDYxZmM5MTQtZWFhYy00YjQ4LTgyMmEtMmE3OTNlZDMzZGYwIiwiZW1haWwiOiJNb2hhbWVkLlJlc3dhbkBjbG91ZHNvbHV0aW9uLXNhLmNvbSIsImlkIjoiMjgwNCIsIk5hbWUiOiJNVUhBTU1BRCBBWkFNIiwiRW1wbG95ZWVJZCI6IjE0ODUiLCJGYWNpbGl0eUdyb3VwSWQiOiIwMTAyNjYiLCJGYWNpbGl0eUlkIjoiMTUiLCJQaGFyYW1jeUZhY2lsaXR5SWQiOiI1NSIsIklTX1BIQVJNQUNZX0NPTk5FQ1RFRCI6IlRydWUiLCJEb2N0b3JJZCI6IjE0ODUiLCJTRVNTSU9OSUQiOiIyMTU3NTgwOCIsIkNsaW5pY0lkIjoiMyIsInJvbGUiOlsiU0VDVVJJVFkgQURNSU5JU1RSQVRPUlMiLCJTRVRVUCBBRE1JTklTVFJBVE9SUyIsIkNFTydTIiwiRVhFQ1VUSVZFIERJUkVDVE9SUyIsIk1BTkFHRVJTIiwiU1VQRVJWSVNPUlMiLCJDTElFTlQgU0VSVklDRVMgQ09PUkRJTkFUT1JTIiwiQ0xJRU5UIFNFUlZJQ0VTIFNVUEVSVklTT1JTIiwiQ0xJRU5UIFNFUlZJQ0VTIE1BTkdFUlMiLCJIRUFEIE5VUlNFUyIsIkRPQ1RPUlMiLCJDSElFRiBPRiBNRURJQ0FMIFNUQUZGUyIsIkJJTy1NRURJQ0FMIFRFQ0hOSUNJQU5TIiwiQklPLU1FRElDQUwgRU5HSU5FRVJTIiwiQklPLU1FRElDQUwgREVQQVJUTUVOVCBIRUFEUyIsIklUIEhFTFAgREVTSyIsIkFETUlOSVNUUkFUT1JTIiwiTEFCIEFETUlOSVNUUkFUT1IiLCJMQUIgVEVDSE5JQ0lBTiIsIkJVU0lORVNTIE9GRklDRSBTVEFGRiIsIkZJTkFOQ0UgQUNDT1VOVEFOVFMiLCJQSEFSTUFDWSBTVEFGRiIsIkFDQ09VTlRTIFNUQUZGIiwiTEFCIFJFQ0VQVElPTklTVCIsIkVSIE5VUlNFIiwiSU5QQVRJRU5UIEJJTExJTkcgU1VQRVJWSVNPUiIsIkxEUi1PUiBOVVJTRVMiLCJBRE1JU1NJT04gU1RBRkYiLCJIRUxQIERFU0sgQURNSU4iLCJBUFBST1ZBTCBTVEFGRiIsIklOUEFUSUVOVCBCSUxMSU5HIENPT1JESU5BVE9SIiwiQklMTElORyBTVEFGRiIsIkNPTlNFTlQgIiwiQ29uc2VudCAtIERlbnRhbCIsIldFQkVNUiJdLCJuYmYiOjE2MDgwMjg0NzQsImV4cCI6MTYwODg5MjQ3NCwiaWF0IjoxNjA4MDI4NDc0fQ.8OJcy6vUuPnNTi_qSjip8YCrFdaRLtJKbNKXcMtnQxk"
},
);
}
@@ -48,4 +48,5 @@ class DashboardService extends BaseService {
},
);
}
+
}
diff --git a/lib/core/service/home/scan_qr_service.dart b/lib/core/service/home/scan_qr_service.dart
new file mode 100644
index 00000000..bc6c8820
--- /dev/null
+++ b/lib/core/service/home/scan_qr_service.dart
@@ -0,0 +1,41 @@
+import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
+import 'package:doctor_app_flutter/core/service/base/base_service.dart';
+import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
+
+class ScanQrService extends BaseService {
+ List myInPatientList = List();
+ List inPatientList = List();
+
+ Future getInPatient(PatientSearchRequestModel requestModel, bool isMyInpatient) async {
+ hasError = false;
+ await getDoctorProfile();
+
+ if (isMyInpatient) {
+ requestModel.doctorID = doctorProfile.doctorID;
+ } else {
+ requestModel.doctorID = 0;
+ }
+
+ await baseAppClient.post(
+ GET_PATIENT_IN_PATIENT_LIST,
+ onSuccess: (dynamic response, int statusCode) {
+ inPatientList.clear();
+ myInPatientList.clear();
+
+ response['List_MyInPatient'].forEach((v) {
+ PatiantInformtion patient = PatiantInformtion.fromJson(v);
+ inPatientList.add(patient);
+ if (patient.doctorId == doctorProfile.doctorID) {
+ myInPatientList.add(patient);
+ }
+ });
+ },
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: requestModel.toJson(),
+ );
+ }
+}
diff --git a/lib/core/service/patient/LiveCarePatientServices.dart b/lib/core/service/patient/LiveCarePatientServices.dart
index 5b528a33..d8e56db7 100644
--- a/lib/core/service/patient/LiveCarePatientServices.dart
+++ b/lib/core/service/patient/LiveCarePatientServices.dart
@@ -1,5 +1,8 @@
+
import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/core/model/live_care/AlternativeServicesList.dart';
import 'package:doctor_app_flutter/core/model/live_care/PendingPatientERForDoctorAppRequestModel.dart';
+import 'package:doctor_app_flutter/core/model/live_care/live_care_login_reguest_model.dart';
import 'package:doctor_app_flutter/core/service/base/base_service.dart';
import 'package:doctor_app_flutter/models/livecare/end_call_req.dart';
import 'package:doctor_app_flutter/models/livecare/start_call_req.dart';
@@ -11,8 +14,12 @@ class LiveCarePatientServices extends BaseService {
List get patientList => _patientList;
+ List alternativeServicesList = [];
+
bool _isFinished = false;
+ bool _isLive = true;
+
bool get isFinished => _isFinished;
setFinished(bool isFinished) {
@@ -21,12 +28,14 @@ class LiveCarePatientServices extends BaseService {
var endCallResponse = {};
var transferToAdminResponse = {};
+ var isLoginResponse = {};
late StartCallRes _startCallRes;
StartCallRes get startCallRes => _startCallRes;
Future getPendingPatientERForDoctorApp(
- PendingPatientERForDoctorAppRequestModel pendingPatientERForDoctorAppRequestModel) async {
+ PendingPatientERForDoctorAppRequestModel
+ pendingPatientERForDoctorAppRequestModel) async {
hasError = false;
await baseAppClient.post(
GET_PENDING_PATIENT_ER_FOR_DOCTOR_APP,
@@ -51,7 +60,7 @@ class LiveCarePatientServices extends BaseService {
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
- }, body: endCallReq.toJson(), isLiveCare: true);
+ }, body: endCallReq.toJson(), isLiveCare: _isLive);
}
Future startCall(StartCallReq startCallReq) async {
@@ -61,10 +70,10 @@ class LiveCarePatientServices extends BaseService {
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
- }, body: startCallReq.toJson(), isLiveCare: true);
+ }, body: startCallReq.toJson(), isLiveCare: _isLive);
}
- Future endCallWithCharge(int vcID) async {
+ Future endCallWithCharge(int vcID, List altServiceList) async {
hasError = false;
await baseAppClient.post(END_CALL_WITH_CHARGE, onSuccess: (dynamic response, int statusCode) {
endCallResponse = response;
@@ -73,8 +82,8 @@ class LiveCarePatientServices extends BaseService {
super.error = error;
}, body: {
"VC_ID": vcID,
- "generalid": "Cs2020@2016\$2958",
- }, isLiveCare: true);
+ "AltServiceList": altServiceList,"generalid": GENERAL_ID
+ }, isLiveCare: _isLive);
}
Future transferToAdmin(int vcID, String notes) async {
@@ -88,6 +97,49 @@ class LiveCarePatientServices extends BaseService {
"VC_ID": vcID,
"IsOutKsa": false,
"Notes": notes,
- }, isLiveCare: true);
+ }, isLiveCare: _isLive);
+ }
+
+ Future sendSMSInstruction(int vcID) async {
+ hasError = false;
+ await baseAppClient.post(SEND_SMS_INSTRUCTIONS,
+ onSuccess: (dynamic response, int statusCode) {
+ transferToAdminResponse = response;
+ }, onFailure: (String error, int statusCode) {
+ hasError =true;
+ super.error = error;
+ }, body: {
+ "VC_ID": vcID, "generalid": GENERAL_ID
+ }, isLiveCare: _isLive);
+ }
+
+ Future isLogin({LiveCareUserLoginRequestModel isLoginRequestModel, int loginStatus}) async {
+ hasError = false;
+ await getDoctorProfile( );
+ isLoginRequestModel.doctorId = super.doctorProfile.doctorID;
+ await baseAppClient.post(LIVE_CARE_IS_LOGIN, onSuccess: (response, statusCode) async {
+ isLoginResponse = response;
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: isLoginRequestModel.toJson(), isLiveCare: _isLive);
+ }
+
+ Future getAlternativeServices(int vcID) async {
+ hasError = false;
+ alternativeServicesList.clear();
+
+ await baseAppClient.post(GET_ALTERNATIVE_SERVICE,
+ onSuccess: (dynamic response, int statusCode) {
+ response['AlternativeServicesList'].forEach((v) {
+ alternativeServicesList.add(AlternativeService.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "VC_ID": vcID,
+ "generalid": GENERAL_ID
+ }, isLiveCare: _isLive);
}
}
diff --git a/lib/core/service/patient/MyReferralPatientService.dart b/lib/core/service/patient/MyReferralPatientService.dart
index d1ef47fa..c2e467d2 100644
--- a/lib/core/service/patient/MyReferralPatientService.dart
+++ b/lib/core/service/patient/MyReferralPatientService.dart
@@ -1,5 +1,7 @@
import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/core/model/referral/MyReferralPatientModel.dart';
+import 'package:doctor_app_flutter/core/model/referral/MyReferralPatientRequestModel.dart';
+import 'package:doctor_app_flutter/core/model/referral/add_referred_remarks_request.dart';
import 'package:doctor_app_flutter/core/service/base/base_service.dart';
import 'package:doctor_app_flutter/models/doctor/request_add_referred_doctor_remarks.dart';
@@ -8,22 +10,21 @@ class MyReferralInPatientService extends BaseService {
Future getMyReferralPatientService() async {
hasError = false;
- Map body = Map();
await getDoctorProfile();
- body['DoctorID'] = doctorProfile!.doctorID;
- body['FirstName'] = "0";
- body['MiddleName'] = "0";
- body['LastName'] = "0";
- body['PatientMobileNumber'] = "0";
- body['PatientIdentificationID'] = "0";
- body['PatientID'] = 0;
- body['From'] = "0";
- body['To'] = "0";
- body['stamp'] = DateTime.now().toIso8601String();
- body['IsLoginForDoctorApp'] = true;
- body['IPAdress'] = "11.11.11.11";
- body['PatientOutSA'] = false;
- body['PatientTypeID'] = 1;
+
+ MyReferralPatientRequestModel myReferralPatientRequestModel = MyReferralPatientRequestModel(
+ doctorID: doctorProfile!.doctorID,
+ firstName: "0",
+ middleName: "0",
+ lastName: "0",
+ patientMobileNumber: "0",
+ patientIdentificationID: "0",
+ patientID: 0,
+ from: "0",
+ to: "0",
+ stamp: DateTime.now().toIso8601String(),
+ isLoginForDoctorApp: true,
+ patientTypeID: 1);
myReferralPatients.clear();
await baseAppClient.post(
GET_MY_REFERRAL_INPATIENT,
@@ -38,7 +39,42 @@ class MyReferralInPatientService extends BaseService {
hasError = true;
super.error = error;
},
- body: body,
+ body: myReferralPatientRequestModel.toJson(),
+ );
+ }
+
+ Future getMyReferralOutPatientService() async {
+ hasError = false;
+ await getDoctorProfile();
+
+ MyReferralPatientRequestModel myReferralPatientRequestModel = MyReferralPatientRequestModel(
+ doctorID: doctorProfile.doctorID,
+ firstName: "0",
+ middleName: "0",
+ lastName: "0",
+ patientMobileNumber: "0",
+ patientIdentificationID: "0",
+ patientID: 0,
+ from: "0",
+ to: "0",
+ stamp: DateTime.now().toIso8601String(),
+ isLoginForDoctorApp: true,
+ patientTypeID: 1);
+ myReferralPatients.clear();
+ await baseAppClient.post(
+ GET_MY_REFERRAL_OUT_PATIENT,
+ onSuccess: (dynamic response, int statusCode) {
+ if (response['List_MyOutPatientReferral'] != null) {
+ response['List_MyOutPatientReferral'].forEach((v) {
+ myReferralPatients.add(MyReferralPatientModel.fromJson(v));
+ });
+ }
+ },
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: myReferralPatientRequestModel.toJson(),
);
}
@@ -63,4 +99,32 @@ class MyReferralInPatientService extends BaseService {
},
);
}
+
+ Future replayReferred(String referredDoctorRemarks, MyReferralPatientModel referral, int referalStatus) async {
+ hasError = false;
+ await getDoctorProfile();
+ AddReferredRemarksRequestModel _requestAddReferredDoctorRemarks = AddReferredRemarksRequestModel(
+ editedBy: doctorProfile.doctorID,
+ projectID: doctorProfile.projectID,
+ referredDoctorRemarks: referredDoctorRemarks,
+ referalStatus: referalStatus);
+ _requestAddReferredDoctorRemarks.projectID = referral.projectID;
+ _requestAddReferredDoctorRemarks.admissionNo = int.parse(referral.admissionNo);
+ _requestAddReferredDoctorRemarks.lineItemNo = referral.lineItemNo;
+ _requestAddReferredDoctorRemarks.referredDoctorRemarks = referredDoctorRemarks;
+ _requestAddReferredDoctorRemarks.editedBy = doctorProfile.doctorID;
+ _requestAddReferredDoctorRemarks.referalStatus = referalStatus;
+
+ // _requestAddReferredDoctorRemarks.patientID = referral.patientID;
+ // _requestAddReferredDoctorRemarks.referringDoctor = referral.referringDoctor;
+ await baseAppClient.post(
+ ADD_REFERRED_REMARKS_NEW,
+ body: _requestAddReferredDoctorRemarks.toJson(),
+ onSuccess: (dynamic body, int statusCode) {},
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ );
+ }
}
diff --git a/lib/core/service/patient/patient-doctor-referral-service.dart b/lib/core/service/patient/patient-doctor-referral-service.dart
index abf3fab3..08e17574 100644
--- a/lib/core/service/patient/patient-doctor-referral-service.dart
+++ b/lib/core/service/patient/patient-doctor-referral-service.dart
@@ -151,6 +151,36 @@ class PatientReferralService extends LookupService {
);
}
+ Future getMyReferredOutPatient() async {
+ hasError = false;
+ RequestMyReferralPatientModel _requestMyReferralPatient =
+ RequestMyReferralPatientModel();
+ DoctorProfileModel doctorProfile = await getDoctorProfile();
+
+ await baseAppClient.post(
+ GET_MY_REFERRED_OUT_PATIENT,
+ onSuccess: (dynamic response, int statusCode) {
+ listMyReferredPatientModel.clear();
+
+ response['List_MyReferredOutPatient'].forEach((v) {
+ MyReferredPatientModel item = MyReferredPatientModel.fromJson(v);
+ if (doctorProfile != null) {
+ item.isReferralDoctorSameBranch =
+ doctorProfile.projectID == item.projectID;
+ } else {
+ item.isReferralDoctorSameBranch = false;
+ }
+ listMyReferredPatientModel.add(item);
+ });
+ },
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: _requestMyReferralPatient.toJson(),
+ );
+ }
+
Future getPendingReferralList() async {
hasError = false;
DoctorProfileModel? doctorProfile = await getDoctorProfile();
diff --git a/lib/core/service/patient/patient_service.dart b/lib/core/service/patient/patient_service.dart
index 8eedb7de..31632d27 100644
--- a/lib/core/service/patient/patient_service.dart
+++ b/lib/core/service/patient/patient_service.dart
@@ -4,6 +4,7 @@ import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
import 'package:doctor_app_flutter/core/model/note/CreateNoteModel.dart';
import 'package:doctor_app_flutter/core/model/note/note_model.dart';
import 'package:doctor_app_flutter/core/model/note/update_note_model.dart';
+import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
import 'package:doctor_app_flutter/core/service/base/base_service.dart';
import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart';
import 'package:doctor_app_flutter/models/patient/get_clinic_by_project_id_request.dart';
@@ -12,6 +13,7 @@ import 'package:doctor_app_flutter/models/patient/get_list_stp_referral_frequenc
import 'package:doctor_app_flutter/models/patient/lab_orders/lab_orders_res_model.dart';
import 'package:doctor_app_flutter/models/patient/lab_result/lab_result.dart';
import 'package:doctor_app_flutter/models/patient/lab_result/lab_result_req_model.dart';
+import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_report.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_report_for_in_patient.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_res_model.dart';
@@ -22,6 +24,8 @@ import 'package:doctor_app_flutter/models/patient/vital_sign/vital_sign_res_mode
class PatientService extends BaseService {
List _patientVitalSignList = [];
List patientVitalSignOrderdSubList = [];
+ List inPatientList = List();
+ List myInPatientList = List();
List get patientVitalSignList => _patientVitalSignList;
@@ -132,6 +136,38 @@ class PatientService extends BaseService {
return Future.value(localRes);
}
+ Future getInPatient(PatientSearchRequestModel requestModel, bool isMyInpatient) async {
+ hasError = false;
+ await getDoctorProfile();
+
+ if (isMyInpatient) {
+ requestModel.doctorID = doctorProfile.doctorID;
+ } else {
+ requestModel.doctorID = 0;
+ }
+
+ await baseAppClient.post(
+ GET_PATIENT_IN_PATIENT_LIST,
+ onSuccess: (dynamic response, int statusCode) {
+ inPatientList.clear();
+ myInPatientList.clear();
+
+ response['List_MyInPatient'].forEach((v) {
+ PatiantInformtion patient = PatiantInformtion.fromJson(v);
+ inPatientList.add(patient);
+ if (patient.doctorId == doctorProfile.doctorID) {
+ myInPatientList.add(patient);
+ }
+ });
+ },
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: requestModel.toJson(),
+ );
+ }
+
Future getLabResultOrders(patient) async {
hasError = false;
await baseAppClient.post(
diff --git a/lib/core/service/patient/referred_patient_service.dart b/lib/core/service/patient/referred_patient_service.dart
deleted file mode 100644
index 0af9b077..00000000
--- a/lib/core/service/patient/referred_patient_service.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:doctor_app_flutter/config/config.dart';
-import 'package:doctor_app_flutter/core/service/base/base_service.dart';
-import 'package:doctor_app_flutter/models/doctor/verify_referral_doctor_remarks.dart';
-import 'package:doctor_app_flutter/models/patient/my_referral/my_referred_patient_model.dart';
-import 'package:doctor_app_flutter/models/patient/request_my_referral_patient_model.dart';
-
-class ReferredPatientService extends BaseService {
- List _listMyReferredPatientModel = [];
-
- List get listMyReferredPatientModel =>
- _listMyReferredPatientModel;
-
- RequestMyReferralPatientModel _requestMyReferralPatient =
- RequestMyReferralPatientModel();
- VerifyReferralDoctorRemarks _verifyreferraldoctorremarks =
- VerifyReferralDoctorRemarks();
-
- Future getMyReferredPatient() async {
- await baseAppClient.post(
- GET_MY_REFERRED_PATIENT,
- onSuccess: (dynamic response, int statusCode) {
- _listMyReferredPatientModel.clear();
- response['List_MyReferredPatient'].forEach((v) {
- listMyReferredPatientModel.add(MyReferredPatientModel.fromJson(v));
- });
- // print(response['List_MyReferredPatient']);
- },
- onFailure: (String error, int statusCode) {
- hasError = true;
- super.error = error;
- },
- body: _requestMyReferralPatient.toJson(),
- );
- }
-
-}
diff --git a/lib/core/service/patient_medical_file/procedure/procedure_service.dart b/lib/core/service/patient_medical_file/procedure/procedure_service.dart
index 6a757986..48a93853 100644
--- a/lib/core/service/patient_medical_file/procedure/procedure_service.dart
+++ b/lib/core/service/patient_medical_file/procedure/procedure_service.dart
@@ -61,7 +61,7 @@ class ProcedureService extends BaseService {
Future getProcedureTemplate({int? doctorId, int? projectId, int? clinicId, String? categoryID}) async {
_procedureTempleteRequestModel = ProcedureTempleteRequestModel(
- tokenID: "@dm!n",
+ // tokenID: "@dm!n",
patientID: 0,
searchType: 1,
);
diff --git a/lib/core/service/patient_medical_file/radiology/radiology_service.dart b/lib/core/service/patient_medical_file/radiology/radiology_service.dart
index 771ee179..63dcd188 100644
--- a/lib/core/service/patient_medical_file/radiology/radiology_service.dart
+++ b/lib/core/service/patient_medical_file/radiology/radiology_service.dart
@@ -40,6 +40,9 @@ class RadiologyService extends BaseService {
if (isInPatient) {
label = "List_GetRadOreders";
}
+ if(response[label] == null || response[label].length == 0){
+ label = "FinalRadiologyList";
+ }
response[label].forEach((radiology) {
finalRadiologyList.add(FinalRadiology.fromJson(radiology));
});
diff --git a/lib/core/service/special_clinics/special_clinic_service.dart b/lib/core/service/special_clinics/special_clinic_service.dart
new file mode 100644
index 00000000..49237331
--- /dev/null
+++ b/lib/core/service/special_clinics/special_clinic_service.dart
@@ -0,0 +1,57 @@
+import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/core/service/base/base_service.dart';
+import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
+import 'package:doctor_app_flutter/models/dashboard/get_special_clinical_care_List_Respose_Model.dart';
+import 'package:doctor_app_flutter/models/dashboard/get_special_clinical_care_mapping_List_Respose_Model.dart';
+
+class SpecialClinicsService extends BaseService {
+
+
+ List _specialClinicalCareList = [];
+ List get specialClinicalCareList => _specialClinicalCareList;
+
+ List _specialClinicalCareMappingList = [];
+ List get specialClinicalCareMappingList => _specialClinicalCareMappingList;
+ Future getSpecialClinicalCareList() async {
+ hasError = false;
+ await baseAppClient.post(
+ GET_SPECIAL_CLINICAL_CARE_LIST,
+ onSuccess: (dynamic response, int statusCode) {
+
+ _specialClinicalCareList.clear();
+ response['List_SpecialClinicalCareList'].forEach((v) {
+ _specialClinicalCareList.add(GetSpecialClinicalCareListResponseModel.fromJson(v));
+ });},
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: {
+ },
+ );
+ }
+
+
+ Future getSpecialClinicalCareMappingList(int clinicId) async {
+ hasError = false;
+ await baseAppClient.post(
+ GET_SPECIAL_CLINICAL_CARE_MAPPING_LIST,
+ onSuccess: (dynamic response, int statusCode) {
+
+ _specialClinicalCareMappingList.clear();
+ response['List_SpecialClinicalCareMappingList'].forEach((v) {
+ _specialClinicalCareMappingList.add(GetSpecialClinicalCareMappingListResponseModel.fromJson(v));
+ });},
+ onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ },
+ body: {
+ "ClinicID": clinicId,
+ "DoctorID":0,
+ "EditedBy":0
+ },
+ );
+ }
+
+}
diff --git a/lib/core/viewModel/LiveCarePatientViewModel.dart b/lib/core/viewModel/LiveCarePatientViewModel.dart
index c963e0f9..907bc1da 100644
--- a/lib/core/viewModel/LiveCarePatientViewModel.dart
+++ b/lib/core/viewModel/LiveCarePatientViewModel.dart
@@ -1,6 +1,8 @@
import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
import 'package:doctor_app_flutter/core/enum/viewstate.dart';
+import 'package:doctor_app_flutter/core/model/live_care/AlternativeServicesList.dart';
import 'package:doctor_app_flutter/core/model/live_care/PendingPatientERForDoctorAppRequestModel.dart';
+import 'package:doctor_app_flutter/core/model/live_care/live_care_login_reguest_model.dart';
import 'package:doctor_app_flutter/core/service/home/dasboard_service.dart';
import 'package:doctor_app_flutter/core/service/patient/LiveCarePatientServices.dart';
import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart';
@@ -18,6 +20,9 @@ class LiveCarePatientViewModel extends BaseViewModel {
StartCallRes get startCallRes => _liveCarePatientServices.startCallRes;
+ List get alternativeServicesList =>
+ _liveCarePatientServices.alternativeServicesList;
+
DashboardService _dashboardService = locator();
getPendingPatientERForDoctorApp({bool isFromTimer = false}) async {
@@ -87,9 +92,22 @@ class LiveCarePatientViewModel extends BaseViewModel {
}
}
- Future endCallWithCharge(int vcID) async {
+ setSelectedCheckboxValues(AlternativeService service, bool isSelected) {
+ int index = alternativeServicesList.indexOf(service);
+ if (index != -1) alternativeServicesList[index].isSelected = isSelected;
+ notifyListeners();
+ }
+
+ Future endCallWithCharge(int vcID, bool isConfirmed) async {
setState(ViewState.BusyLocal);
- await _liveCarePatientServices.endCallWithCharge(vcID);
+
+ List selectedServices = [];
+ if (isConfirmed) {
+ selectedServices = getSelectedAlternativeServices();
+ }
+
+ await _liveCarePatientServices.endCallWithCharge(
+ vcID, selectedServices);
if (_liveCarePatientServices.hasError) {
error = _liveCarePatientServices.error!;
setState(ViewState.ErrorLocal);
@@ -99,6 +117,27 @@ class LiveCarePatientViewModel extends BaseViewModel {
}
}
+ List getSelectedAlternativeServices() {
+ List selectedServices = List();
+ for (AlternativeService service in alternativeServicesList) {
+ if (service.isSelected) {
+ selectedServices.add(service.serviceID);
+ }
+ }
+ return selectedServices;
+ }
+
+ Future getAlternativeServices(int vcID) async {
+ setState(ViewState.BusyLocal);
+ await _liveCarePatientServices.getAlternativeServices(vcID);
+ if (_liveCarePatientServices.hasError) {
+ error = _liveCarePatientServices.error;
+ setState(ViewState.ErrorLocal);
+ } else {
+ setState(ViewState.Idle);
+ }
+ }
+
Future transferToAdmin(int vcID, String notes) async {
setState(ViewState.BusyLocal);
await _liveCarePatientServices.transferToAdmin(vcID, notes);
@@ -111,6 +150,18 @@ class LiveCarePatientViewModel extends BaseViewModel {
}
}
+ Future sendSMSInstruction(int vcID) async {
+ setState(ViewState.BusyLocal);
+ await _liveCarePatientServices.sendSMSInstruction(vcID);
+ if (_liveCarePatientServices.hasError) {
+ error = _liveCarePatientServices.error;
+ setState(ViewState.ErrorLocal);
+ } else {
+ await getPendingPatientERForDoctorApp();
+ setState(ViewState.Idle);
+ }
+ }
+
searchData(String str) {
var strExist = str.length > 0 ? true : false;
if (strExist) {
@@ -130,4 +181,61 @@ class LiveCarePatientViewModel extends BaseViewModel {
notifyListeners();
}
}
+
+ Future isLogin(int loginStatus) async {
+ await getDoctorProfile(isGetProfile: true);
+
+ LiveCareUserLoginRequestModel userLoginRequestModel = new LiveCareUserLoginRequestModel();
+ userLoginRequestModel.isOutKsa = (doctorProfile.projectID == 2 || doctorProfile.projectID == 3) ? 1 : 0;
+ userLoginRequestModel.isLogin = loginStatus;
+ userLoginRequestModel.generalid = "Cs2020@2016\$2958";
+
+ setState(ViewState.BusyLocal);
+ await _liveCarePatientServices.isLogin(loginStatus: loginStatus, isLoginRequestModel: userLoginRequestModel);
+ if (_liveCarePatientServices.hasError) {
+ error = _liveCarePatientServices.error;
+ setState(ViewState.ErrorLocal);
+ } else {
+ setState(ViewState.Idle);
+ }
+ }
+
+ setDemoData() {
+ alternativeServicesList.clear();
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 1, serviceName: "Medicine Home Delivery"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 2, serviceName: "LABORATORY"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(
+ serviceID: 3, serviceName: "RADIOLOGY(ULTRASOUND) For pregnant only"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 4, serviceName: "VACCINATIONS"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 5, serviceName: "ER SERVICES"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 6, serviceName: "PHYSIOTHERAPY"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 7, serviceName: "DRESSING"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 8, serviceName: "INJECTION"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 9, serviceName: "FAMILY MEDICIN DR"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(
+ serviceID: 10, serviceName: "FOLYS CATHETER INSERTION"),
+ );
+ alternativeServicesList.add(
+ AlternativeService(serviceID: 11, serviceName: "GASTRIC TUBE CHANGE"),
+ );
+ }
}
diff --git a/lib/core/viewModel/PatientMedicalReportViewModel.dart b/lib/core/viewModel/PatientMedicalReportViewModel.dart
index 4a9045be..8dbbc64d 100644
--- a/lib/core/viewModel/PatientMedicalReportViewModel.dart
+++ b/lib/core/viewModel/PatientMedicalReportViewModel.dart
@@ -25,12 +25,24 @@ class PatientMedicalReportViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
+ bool hasOnHold(){
+ bool hasHold = false;
+ medicalReportList.forEach((element) {
+ if(element.status == 1){
+ hasHold = true;
+ }
+ });
+
+ return hasHold;
+
+ }
+
Future getMedicalReportTemplate() async {
- setState(ViewState.Busy);
+ setState(ViewState.BusyLocal);
await _service.getMedicalReportTemplate();
if (_service.hasError) {
error = _service.error!;
- setState(ViewState.Error);
+ setState(ViewState.ErrorLocal);
} else
setState(ViewState.Idle);
}
diff --git a/lib/core/viewModel/PatientSearchViewModel.dart b/lib/core/viewModel/PatientSearchViewModel.dart
index 9cc1110b..d0bd9862 100644
--- a/lib/core/viewModel/PatientSearchViewModel.dart
+++ b/lib/core/viewModel/PatientSearchViewModel.dart
@@ -4,6 +4,8 @@ import 'package:doctor_app_flutter/core/enum/viewstate.dart';
import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
import 'package:doctor_app_flutter/core/service/patient/out_patient_service.dart';
import 'package:doctor_app_flutter/core/service/patient/patientInPatientService.dart';
+import 'package:doctor_app_flutter/core/service/special_clinics/special_clinic_service.dart';
+import 'package:doctor_app_flutter/models/dashboard/get_special_clinical_care_mapping_List_Respose_Model.dart';
import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/util/date-utils.dart';
@@ -12,8 +14,10 @@ import 'base_view_model.dart';
class PatientSearchViewModel extends BaseViewModel {
OutPatientService _outPatientService = locator();
+ SpecialClinicsService _specialClinicsService = locator();
List get patientList => _outPatientService.patientList;
+ List get specialClinicalCareMappingList => _specialClinicsService.specialClinicalCareMappingList;
List filterData = [];
@@ -123,14 +127,21 @@ class PatientSearchViewModel extends BaseViewModel {
List filteredInPatientItems = [];
- Future getInPatientList(PatientSearchRequestModel requestModel, {bool isMyInpatient = false}) async {
+ Future getInPatientList(PatientSearchRequestModel requestModel, {bool isMyInpatient = false, bool isLocalBusy = false}) async {
await getDoctorProfile();
- setState(ViewState.Busy);
-
+ if(isLocalBusy) {
+ setState(ViewState.BusyLocal);
+ } else{
+ setState(ViewState.Busy);
+ }
if (inPatientList.length == 0) await _inPatientService.getInPatientList(requestModel, false);
if (_inPatientService.hasError) {
error = _inPatientService.error!;
+ if(isLocalBusy) {
+ setState(ViewState.ErrorLocal);
+ } else{
setState(ViewState.Error);
+ }
} else {
// setDefaultInPatientList();
setState(ViewState.Idle);
@@ -145,6 +156,9 @@ class PatientSearchViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
+
+
+
void clearPatientList() {
_inPatientService.inPatientList = [];
_inPatientService.myInPatientList = [];
@@ -174,4 +188,25 @@ class PatientSearchViewModel extends BaseViewModel {
notifyListeners();
}
}
+
+
+ getSpecialClinicalCareMappingList(clinicId,
+ {bool isLocalBusy = false}) async {
+ if (isLocalBusy) {
+ setState(ViewState.BusyLocal);
+ } else {
+ setState(ViewState.Busy);
+ }
+ await _specialClinicsService.getSpecialClinicalCareMappingList(clinicId);
+ if (_specialClinicsService.hasError) {
+ error = _specialClinicsService.error;
+ if (isLocalBusy) {
+ setState(ViewState.ErrorLocal);
+ } else {
+ setState(ViewState.Error);
+ }
+ } else {
+ setState(ViewState.Idle);
+ }
+ }
}
diff --git a/lib/core/viewModel/authentication_view_model.dart b/lib/core/viewModel/authentication_view_model.dart
index a6692563..f63220d4 100644
--- a/lib/core/viewModel/authentication_view_model.dart
+++ b/lib/core/viewModel/authentication_view_model.dart
@@ -26,9 +26,7 @@ import 'package:doctor_app_flutter/root_page.dart';
import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart';
import 'package:doctor_app_flutter/util/helpers.dart';
import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
-import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
-import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:local_auth/auth_strings.dart';
import 'package:local_auth/local_auth.dart';
@@ -234,7 +232,8 @@ class AuthenticationViewModel extends BaseViewModel {
/// add token to shared preferences in case of send activation code is success
setDataAfterSendActivationSuccess(
SendActivationCodeForDoctorAppResponseModel sendActivationCodeForDoctorAppResponseModel) {
- print("VerificationCode : " + sendActivationCodeForDoctorAppResponseModel.verificationCode!);
+ print("VerificationCode : " +sendActivationCodeForDoctorAppResponseModel.verificationCode);
+ // DrAppToastMsg.showSuccesToast("VerificationCode : " + sendActivationCodeForDoctorAppResponseModel.verificationCode!);
sharedPref.setString(VIDA_AUTH_TOKEN_ID, sendActivationCodeForDoctorAppResponseModel.vidaAuthTokenID!);
sharedPref.setString(VIDA_REFRESH_TOKEN_ID, sendActivationCodeForDoctorAppResponseModel.vidaRefreshTokenID!);
sharedPref.setString(LOGIN_TOKEN_ID, sendActivationCodeForDoctorAppResponseModel.logInTokenID!);
@@ -275,8 +274,7 @@ class AuthenticationViewModel extends BaseViewModel {
clinicID: clinicInfo.clinicID,
license: true,
projectID: clinicInfo.projectID,
- tokenID: '',
- languageID: 2); //TODO change the lan
+ tokenID: '',); //TODO change the lan
await _authService.getDoctorProfileBasedOnClinic(docInfo);
if (_authService.hasError) {
error = _authService.error!;
diff --git a/lib/core/viewModel/dashboard_view_model.dart b/lib/core/viewModel/dashboard_view_model.dart
index 8fe5a88c..e85c103c 100644
--- a/lib/core/viewModel/dashboard_view_model.dart
+++ b/lib/core/viewModel/dashboard_view_model.dart
@@ -2,8 +2,10 @@ import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
import 'package:doctor_app_flutter/core/enum/viewstate.dart';
import 'package:doctor_app_flutter/core/service/home/dasboard_service.dart';
+import 'package:doctor_app_flutter/core/service/special_clinics/special_clinic_service.dart';
import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart';
import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
+import 'package:doctor_app_flutter/models/dashboard/get_special_clinical_care_List_Respose_Model.dart';
import 'package:doctor_app_flutter/models/doctor/clinic_model.dart';
import 'package:doctor_app_flutter/models/doctor/profile_req_Model.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
@@ -14,6 +16,7 @@ import 'base_view_model.dart';
class DashboardViewModel extends BaseViewModel {
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
DashboardService _dashboardService = locator();
+ SpecialClinicsService _specialClinicsService = locator();
List get dashboardItemsList => _dashboardService.dashboardItemsList;
@@ -21,6 +24,9 @@ class DashboardViewModel extends BaseViewModel {
String? get sServiceID => _dashboardService.sServiceID;
+ List get specialClinicalCareList => _specialClinicsService.specialClinicalCareList;
+
+
Future setFirebaseNotification(ProjectViewModel projectsProvider, AuthenticationViewModel authProvider) async {
setState(ViewState.Busy);
await projectsProvider.getDoctorClinicsList();
@@ -56,6 +62,16 @@ class DashboardViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
+ Future getSpecialClinicalCareList() async {
+ setState(ViewState.Busy);
+ await _specialClinicsService.getSpecialClinicalCareList();
+ if (_specialClinicsService.hasError) {
+ error = _specialClinicsService.error;
+ setState(ViewState.Error);
+ } else
+ setState(ViewState.Idle);
+ }
+
Future changeClinic(int clinicId, AuthenticationViewModel authProvider) async {
setState(ViewState.BusyLocal);
await getDoctorProfile();
@@ -76,4 +92,17 @@ class DashboardViewModel extends BaseViewModel {
return value.toString();
}
+
+
+ GetSpecialClinicalCareListResponseModel getSpecialClinic(clinicId){
+ GetSpecialClinicalCareListResponseModel special ;
+ specialClinicalCareList.forEach((element) {
+ if(element.clinicID == 1){
+ special = element;
+ }
+ });
+
+ return special;
+
+ }
}
diff --git a/lib/core/viewModel/patient-referral-viewmodel.dart b/lib/core/viewModel/patient-referral-viewmodel.dart
index c1ae248a..520004a4 100644
--- a/lib/core/viewModel/patient-referral-viewmodel.dart
+++ b/lib/core/viewModel/patient-referral-viewmodel.dart
@@ -2,6 +2,7 @@ import 'package:doctor_app_flutter/core/enum/master_lookup_key.dart';
import 'package:doctor_app_flutter/core/enum/viewstate.dart';
import 'package:doctor_app_flutter/core/model/referral/DischargeReferralPatient.dart';
import 'package:doctor_app_flutter/core/model/referral/MyReferralPatientModel.dart';
+import 'package:doctor_app_flutter/core/model/referral/add_referred_remarks_request.dart';
import 'package:doctor_app_flutter/core/service/patient/DischargedPatientService.dart';
import 'package:doctor_app_flutter/core/service/patient/MyReferralPatientService.dart';
import 'package:doctor_app_flutter/core/service/patient/ReferralService.dart';
@@ -119,8 +120,11 @@ class PatientReferralViewModel extends BaseViewModel {
return null;
}
- Future getMyReferredPatient() async {
- setState(ViewState.Busy);
+ Future getMyReferredPatient({bool isFirstTime = true}) async {
+ if (isFirstTime)
+ setState(ViewState.Busy);
+ else
+ setState(ViewState.BusyLocal);
await _referralPatientService.getMyReferredPatient();
if (_referralPatientService.hasError) {
error = _referralPatientService.error!;
@@ -129,6 +133,19 @@ class PatientReferralViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
+ Future getMyReferredOutPatient({bool isFirstTime = true}) async {
+ if (isFirstTime)
+ setState(ViewState.Busy);
+ else
+ setState(ViewState.BusyLocal);
+ await _referralPatientService.getMyReferredOutPatient();
+ if (_referralPatientService.hasError) {
+ error = _referralPatientService.error;
+ setState(ViewState.Error);
+ } else
+ setState(ViewState.Idle);
+ }
+
MyReferredPatientModel getReferredPatientItem(int index) {
return listMyReferredPatientModel[index];
}
@@ -143,12 +160,34 @@ class PatientReferralViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
- Future getMyReferralPatientService() async {
- setState(ViewState.Busy);
+ Future getMyReferralPatientService({bool localBusy = false}) async {
+ if (localBusy)
+ setState(ViewState.BusyLocal);
+ else
+ setState(ViewState.Busy);
await _myReferralService.getMyReferralPatientService();
if (_myReferralService.hasError) {
error = _myReferralService.error!;
- setState(ViewState.Error);
+ if (localBusy)
+ setState(ViewState.ErrorLocal);
+ else
+ setState(ViewState.Error);
+ } else
+ setState(ViewState.Idle);
+ }
+
+ Future getMyReferralOutPatientService({bool localBusy = false}) async {
+ if (localBusy)
+ setState(ViewState.BusyLocal);
+ else
+ setState(ViewState.Busy);
+ await _myReferralService.getMyReferralOutPatientService();
+ if (_myReferralService.hasError) {
+ error = _myReferralService.error;
+ if (localBusy)
+ setState(ViewState.ErrorLocal);
+ else
+ setState(ViewState.Error);
} else
setState(ViewState.Idle);
}
@@ -200,7 +239,7 @@ class PatientReferralViewModel extends BaseViewModel {
patientID: patient.patientId,
roomID: patient.roomId,
referralClinic: clinicID,
- admissionNo: int.parse(patient.admissionNo!), /// TODO Elham* something in case inpateint since we send send appointmentNo for admissionNo which all time null
+ admissionNo: int.parse(patient.admissionNo),
referralDoctor: doctorID,
patientTypeID: patient.patientType,
referringDoctorRemarks: remarks,
@@ -351,4 +390,14 @@ class PatientReferralViewModel extends BaseViewModel {
patient.clinicDescription = referredPatient.clinicDescription!;
return patient;
}
+
+ Future replayReferred(String referredDoctorRemarks, MyReferralPatientModel referral, int referalStatus) async {
+ setState(ViewState.Busy);
+ await _myReferralService.replayReferred(referredDoctorRemarks, referral, referalStatus);
+ if (_myReferralService.hasError) {
+ error = _myReferralService.error;
+ setState(ViewState.ErrorLocal);
+ } else
+ getMyReferralPatientService();
+ }
}
diff --git a/lib/core/viewModel/patient_view_model.dart b/lib/core/viewModel/patient_view_model.dart
index 547dbdec..af0130d8 100644
--- a/lib/core/viewModel/patient_view_model.dart
+++ b/lib/core/viewModel/patient_view_model.dart
@@ -2,9 +2,11 @@ import 'package:doctor_app_flutter/core/enum/viewstate.dart';
import 'package:doctor_app_flutter/core/model/note/CreateNoteModel.dart';
import 'package:doctor_app_flutter/core/model/note/note_model.dart';
import 'package:doctor_app_flutter/core/model/note/update_note_model.dart';
+import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
import 'package:doctor_app_flutter/core/service/patient/patient_service.dart';
import 'package:doctor_app_flutter/models/patient/lab_orders/lab_orders_res_model.dart';
import 'package:doctor_app_flutter/models/patient/lab_result/lab_result.dart';
+import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_report.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_report_for_in_patient.dart';
import 'package:doctor_app_flutter/models/patient/prescription/prescription_res_model.dart';
@@ -17,51 +19,43 @@ import 'base_view_model.dart';
class PatientViewModel extends BaseViewModel {
PatientService _patientService = locator();
- List get patientVitalSignList =>
- _patientService.patientVitalSignList;
+ List get inPatientList => _patientService.inPatientList;
- List get patientVitalSignOrderdSubList =>
- _patientService.patientVitalSignOrderdSubList;
+ List get patientVitalSignList => _patientService.patientVitalSignList;
- List get patientLabResultOrdersList =>
- _patientService.patientLabResultOrdersList;
+ List get patientVitalSignOrderdSubList => _patientService.patientVitalSignOrderdSubList;
- List get patientPrescriptionsList =>
- _patientService.patientPrescriptionsList;
+ List get patientLabResultOrdersList => _patientService.patientLabResultOrdersList;
+
+ List get patientPrescriptionsList => _patientService.patientPrescriptionsList;
List get prescriptionReportForInPatientList =>
_patientService.prescriptionReportForInPatientList;
- List get prescriptionReport =>
- _patientService.prescriptionReport;
+ List get prescriptionReport => _patientService.prescriptionReport;
- List get patientRadiologyList =>
- _patientService.patientRadiologyList;
+ List get patientRadiologyList => _patientService.patientRadiologyList;
List get labResultList => _patientService.labResultList;
get insuranceApporvalsList => _patientService.insuranceApporvalsList;
- List get patientProgressNoteList =>
- _patientService.patientProgressNoteList;
+ List get patientProgressNoteList => _patientService.patientProgressNoteList;
List get clinicsList => _patientService.clinicsList;
List get doctorsList => _patientService.doctorsList;
- List get referralFrequencyList =>
- _patientService.referalFrequancyList;
+ List get referralFrequencyList => _patientService.referalFrequancyList;
- Future getPatientList(patient, patientType,
- {bool isBusyLocal = false, isView}) async {
+ Future getPatientList(patient, patientType, {bool isBusyLocal = false, isView}) async {
var localRes;
if (isBusyLocal) {
setState(ViewState.BusyLocal);
} else {
setState(ViewState.Busy);
}
- localRes = await _patientService.getPatientList(patient, patientType,
- isView: isView);
+ localRes = await _patientService.getPatientList(patient, patientType, isView: isView);
if (_patientService.hasError) {
error = _patientService.error!;
@@ -210,16 +204,12 @@ class PatientViewModel extends BaseViewModel {
}
List getDoctorNameList() {
- var doctorNamelist = _patientService.doctorsList
- .map((value) => value['DoctorName'].toString())
- .toList();
+ var doctorNamelist = _patientService.doctorsList.map((value) => value['DoctorName'].toString()).toList();
return doctorNamelist;
}
List getClinicNameList() {
- var clinicsNameslist = _patientService.clinicsList
- .map((value) => value['ClinicDescription'].toString())
- .toList();
+ var clinicsNameslist = _patientService.clinicsList.map((value) => value['ClinicDescription'].toString()).toList();
return clinicsNameslist;
}
@@ -234,9 +224,8 @@ class PatientViewModel extends BaseViewModel {
}
List getReferralNamesList() {
- var referralNamesList = _patientService.referalFrequancyList
- .map((value) => value['Description'].toString())
- .toList();
+ var referralNamesList =
+ _patientService.referalFrequancyList.map((value) => value['Description'].toString()).toList();
return referralNamesList;
}
@@ -281,4 +270,18 @@ class PatientViewModel extends BaseViewModel {
} else
setState(ViewState.Idle);
}
+
+ Future getInPatientList(PatientSearchRequestModel requestModel, {bool isMyInpatient = false}) async {
+ await getDoctorProfile();
+ setState(ViewState.Busy);
+
+ await _patientService.getInPatient(requestModel, false);
+ if (_patientService.hasError) {
+ error = _patientService.error;
+ setState(ViewState.ErrorLocal);
+ } else {
+ // setDefaultInPatientList();
+ setState(ViewState.Idle);
+ }
+ }
}
diff --git a/lib/core/viewModel/procedure_View_model.dart b/lib/core/viewModel/procedure_View_model.dart
index 43758e65..6fc0f7e1 100644
--- a/lib/core/viewModel/procedure_View_model.dart
+++ b/lib/core/viewModel/procedure_View_model.dart
@@ -4,10 +4,10 @@ import 'package:doctor_app_flutter/core/model/labs/LabOrderResult.dart';
import 'package:doctor_app_flutter/core/model/labs/lab_result.dart';
import 'package:doctor_app_flutter/core/model/labs/patient_lab_orders.dart';
import 'package:doctor_app_flutter/core/model/labs/patient_lab_special_result.dart';
+import 'package:doctor_app_flutter/core/model/procedure/ControlsModel.dart';
import 'package:doctor_app_flutter/core/model/procedure/categories_procedure.dart';
import 'package:doctor_app_flutter/core/model/procedure/get_ordered_procedure_model.dart';
import 'package:doctor_app_flutter/core/model/procedure/post_procedure_req_model.dart';
-import 'package:doctor_app_flutter/core/model/procedure/procedure_templateModel.dart';
import 'package:doctor_app_flutter/core/model/procedure/procedure_template_details_model.dart';
import 'package:doctor_app_flutter/core/model/procedure/procedure_valadate_model.dart';
import 'package:doctor_app_flutter/core/model/procedure/procedure_valadate_request_model.dart';
@@ -19,8 +19,12 @@ import 'package:doctor_app_flutter/core/service/patient_medical_file/radiology/r
import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart';
import 'package:doctor_app_flutter/locator.dart';
import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
+import 'package:doctor_app_flutter/screens/procedures/ProcedureType.dart';
import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart';
+import 'package:doctor_app_flutter/util/helpers.dart';
import 'package:flutter/cupertino.dart';
+import 'package:doctor_app_flutter/core/model/procedure/categories_procedure.dart'
+ as cpe;
class ProcedureViewModel extends BaseViewModel {
//TODO Hussam clean it
@@ -74,11 +78,15 @@ class ProcedureViewModel extends BaseViewModel {
setState(ViewState.Idle);
}
- Future getProcedureCategory({String? categoryName, String? categoryID, patientId}) async {
+ Future getProcedureCategory(
+ {String? categoryName, String? categoryID, patientId}) async {
+ if (categoryName == null) return;
hasError = false;
setState(ViewState.Busy);
await _procedureService.getProcedureCategory(
- categoryName: categoryName, categoryID: categoryID, patientId: patientId);
+ categoryName: categoryName,
+ categoryID: categoryID,
+ patientId: patientId);
if (_procedureService.hasError) {
error = _procedureService.error!;
setState(ViewState.ErrorLocal);
@@ -305,4 +313,70 @@ class ProcedureViewModel extends BaseViewModel {
} else
DrAppToastMsg.showSuccesToast(mes);
}
+
+ Future preparePostProcedure(
+ {String remarks,
+ String orderType,
+ PatiantInformtion patient,
+ List entityList,
+ ProcedureType procedureType}) async {
+ PostProcedureReqModel postProcedureReqModel = new PostProcedureReqModel();
+ ProcedureValadteRequestModel procedureValadteRequestModel =
+ new ProcedureValadteRequestModel();
+ procedureValadteRequestModel.patientMRN = patient.patientMRN;
+ procedureValadteRequestModel.episodeID = patient.episodeNo;
+ procedureValadteRequestModel.appointmentNo = patient.appointmentNo;
+
+ List controlsProcedure = List();
+
+ postProcedureReqModel.appointmentNo = patient.appointmentNo;
+ postProcedureReqModel.episodeID = patient.episodeNo;
+ postProcedureReqModel.patientMRN = patient.patientMRN;
+
+ entityList.forEach((element) {
+ procedureValadteRequestModel.procedure = [element.procedureId];
+ List controls = List();
+ controls.add(
+ Controls(
+ code: "remarks",
+ controlValue: element.remarks != null ? element.remarks : ""),
+ );
+ controls.add(
+ Controls(
+ code: "ordertype",
+ controlValue: procedureType == ProcedureType.PROCEDURE
+ ? element.type ?? "1"
+ : "0"),
+ );
+ controlsProcedure.add(Procedures(
+ category: element.categoryID,
+ procedure: element.procedureId,
+ controls: controls));
+ });
+
+ postProcedureReqModel.procedures = controlsProcedure;
+ await valadteProcedure(procedureValadteRequestModel);
+ if (state == ViewState.Idle) {
+ if (valadteProcedureList[0].entityList.length == 0) {
+ await postProcedure(postProcedureReqModel, patient.patientMRN);
+
+ if (state == ViewState.ErrorLocal) {
+ Helpers.showErrorToast(error);
+ getProcedure(mrn: patient.patientMRN);
+ } else if (state == ViewState.Idle) {
+ DrAppToastMsg.showSuccesToast('procedure has been added');
+ }
+ } else {
+ if (state == ViewState.ErrorLocal) {
+ Helpers.showErrorToast(error);
+ getProcedure(mrn: patient.patientMRN);
+ } else if (state == ViewState.Idle) {
+ Helpers.showErrorToast(
+ valadteProcedureList[0].entityList[0].warringMessages);
+ }
+ }
+ } else {
+ Helpers.showErrorToast(error);
+ }
+ }
}
diff --git a/lib/core/viewModel/referred_view_model.dart b/lib/core/viewModel/referred_view_model.dart
deleted file mode 100644
index da99d26b..00000000
--- a/lib/core/viewModel/referred_view_model.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-import 'package:doctor_app_flutter/core/enum/viewstate.dart';
-import 'package:doctor_app_flutter/core/service/patient/referred_patient_service.dart';
-import 'package:doctor_app_flutter/models/patient/my_referral/my_referred_patient_model.dart';
-
-import '../../locator.dart';
-import 'base_view_model.dart';
-
-class ReferredPatientViewModel extends BaseViewModel {
- ReferredPatientService _referralPatientService = locator();
-
- List get listMyReferredPatientModel => _referralPatientService.listMyReferredPatientModel;
-
- Future getMyReferredPatient() async {
- setState(ViewState.Busy);
- await _referralPatientService.getMyReferredPatient();
- if (_referralPatientService.hasError) {
- error = _referralPatientService.error!;
- setState(ViewState.Error);
- } else
- setState(ViewState.Idle);
- }
-}
diff --git a/lib/core/viewModel/scan_qr_view_model.dart b/lib/core/viewModel/scan_qr_view_model.dart
new file mode 100644
index 00000000..86e975e3
--- /dev/null
+++ b/lib/core/viewModel/scan_qr_view_model.dart
@@ -0,0 +1,26 @@
+import 'package:doctor_app_flutter/core/enum/viewstate.dart';
+import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
+import 'package:doctor_app_flutter/core/service/home/scan_qr_service.dart';
+import 'package:doctor_app_flutter/core/viewModel/base_view_model.dart';
+import 'package:doctor_app_flutter/locator.dart';
+import 'package:doctor_app_flutter/models/patient/patiant_info_model.dart';
+
+class ScanQrViewModel extends BaseViewModel {
+ ScanQrService _scanQrService = locator();
+ List get inPatientList => _scanQrService.inPatientList;
+
+ Future getInPatientList(PatientSearchRequestModel requestModel, {bool isMyInpatient = false}) async {
+ await getDoctorProfile();
+ setState(ViewState.Busy);
+
+ await _scanQrService.getInPatient(requestModel, true);
+ if (_scanQrService.hasError) {
+ error = _scanQrService.error;
+
+ setState(ViewState.ErrorLocal);
+ } else {
+ // setDefaultInPatientList();
+ setState(ViewState.Idle);
+ }
+ }
+}
diff --git a/lib/landing_page.dart b/lib/landing_page.dart
index 90b8453f..0959cd52 100644
--- a/lib/landing_page.dart
+++ b/lib/landing_page.dart
@@ -4,6 +4,7 @@ import 'package:doctor_app_flutter/screens/home/home_screen.dart';
import 'package:doctor_app_flutter/screens/qr_reader/QR_reader_screen.dart';
import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
import 'package:doctor_app_flutter/widgets/shared/app_drawer_widget.dart';
+import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/bottom_nav_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
@@ -32,7 +33,7 @@ class _LandingPageState extends State {
@override
Widget build(BuildContext context) {
- return Scaffold(
+ return AppScaffold(
appBar: currentTab != 0
? AppBar(
elevation: 0,
diff --git a/lib/locator.dart b/lib/locator.dart
index 66ec9161..d74fad8b 100644
--- a/lib/locator.dart
+++ b/lib/locator.dart
@@ -1,42 +1,46 @@
import 'package:doctor_app_flutter/core/service/authentication_service.dart';
+import 'package:doctor_app_flutter/core/service/home/scan_qr_service.dart';
import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/hospitals_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/medical_file_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/patient_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/prescription_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/procedure_View_model.dart';
+import 'package:doctor_app_flutter/core/viewModel/scan_qr_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/sick_leave_view_model.dart';
import 'package:get_it/get_it.dart';
+import 'core/service/NavigationService.dart';
+import 'core/service/VideoCallService.dart';
import 'core/service/home/dasboard_service.dart';
+import 'core/service/home/doctor_reply_service.dart';
+import 'core/service/home/schedule_service.dart';
+import 'core/service/hospitals/hospitals_service.dart';
import 'core/service/patient/DischargedPatientService.dart';
import 'core/service/patient/LiveCarePatientServices.dart';
-import 'core/service/patient/patient_service.dart';
-import 'core/service/patient_medical_file/insurance/InsuranceCardService.dart';
import 'core/service/patient/MyReferralPatientService.dart';
import 'core/service/patient/PatientMuseService.dart';
import 'core/service/patient/ReferralService.dart';
+import 'core/service/patient/out_patient_service.dart';
+import 'core/service/patient/patient-doctor-referral-service.dart';
+import 'core/service/patient/patientInPatientService.dart';
+import 'core/service/patient/patient_service.dart';
+import 'core/service/patient/referral_patient_service.dart';
+import 'core/service/patient_medical_file/admission_request/patient-admission-request-service.dart';
+import 'core/service/patient_medical_file/insurance/InsuranceCardService.dart';
+import 'core/service/patient_medical_file/lab_order/labs_service.dart';
import 'core/service/patient_medical_file/medical_report/PatientMedicalReportService.dart';
import 'core/service/patient_medical_file/medical_report/medical_file_service.dart';
+import 'core/service/patient_medical_file/prescription/medicine_service.dart';
import 'core/service/patient_medical_file/prescription/prescription_service.dart';
+import 'core/service/patient_medical_file/prescription/prescriptions_service.dart';
import 'core/service/patient_medical_file/procedure/procedure_service.dart';
+import 'core/service/patient_medical_file/radiology/radiology_service.dart';
import 'core/service/patient_medical_file/sick_leave/sickleave_service.dart';
import 'core/service/patient_medical_file/soap/SOAP_service.dart';
-import 'core/service/home/doctor_reply_service.dart';
-import 'core/service/hospitals/hospitals_service.dart';
-import 'core/service/patient_medical_file/lab_order/labs_service.dart';
-import 'core/service/patient_medical_file/prescription/medicine_service.dart';
-import 'core/service/patient_medical_file/admission_request/patient-admission-request-service.dart';
-import 'core/service/patient/patient-doctor-referral-service.dart';
import 'core/service/patient_medical_file/ucaf/patient-ucaf-service.dart';
import 'core/service/patient_medical_file/vital_sign/patient-vital-signs-service.dart';
-import 'core/service/patient/out_patient_service.dart';
-import 'core/service/patient/patientInPatientService.dart';
-import 'core/service/patient_medical_file/prescription/prescriptions_service.dart';
-import 'core/service/patient_medical_file/radiology/radiology_service.dart';
-import 'core/service/patient/referral_patient_service.dart';
-import 'core/service/patient/referred_patient_service.dart';
-import 'core/service/home/schedule_service.dart';
+import 'core/service/special_clinics/special_clinic_service.dart';
import 'core/viewModel/DischargedPatientViewModel.dart';
import 'core/viewModel/InsuranceViewModel.dart';
import 'core/viewModel/LiveCarePatientViewModel.dart';
@@ -54,7 +58,6 @@ import 'core/viewModel/patient-vital-sign-viewmodel.dart';
import 'core/viewModel/prescriptions_view_model.dart';
import 'core/viewModel/radiology_view_model.dart';
import 'core/viewModel/referral_view_model.dart';
-import 'core/viewModel/referred_view_model.dart';
import 'core/viewModel/schedule_view_model.dart';
GetIt locator = GetIt.instance;
@@ -65,7 +68,6 @@ void setupLocator() {
locator.registerLazySingleton(() => DoctorReplyService());
locator.registerLazySingleton(() => ScheduleService());
locator.registerLazySingleton(() => ReferralPatientService());
- locator.registerLazySingleton(() => ReferredPatientService());
locator.registerLazySingleton(() => MedicineService());
locator.registerLazySingleton(() => PatientService());
locator.registerLazySingleton(() => DashboardService());
@@ -92,12 +94,15 @@ void setupLocator() {
locator.registerLazySingleton(() => HospitalsService());
locator.registerLazySingleton(() => PatientMedicalReportService());
locator.registerLazySingleton(() => LiveCarePatientServices());
+ locator.registerLazySingleton(() => NavigationService());
+ locator.registerLazySingleton(() => ScanQrService());
+ locator.registerLazySingleton(() => SpecialClinicsService());
+ locator.registerLazySingleton(() => VideoCallService());
/// View Model
locator.registerFactory(() => DoctorReplayViewModel());
locator.registerFactory(() => ScheduleViewModel());
locator.registerFactory(() => ReferralPatientViewModel());
- locator.registerFactory(() => ReferredPatientViewModel());
locator.registerFactory(() => MedicineViewModel());
locator.registerFactory(() => PatientViewModel());
locator.registerFactory(() => DashboardViewModel());
@@ -120,4 +125,5 @@ void setupLocator() {
locator.registerFactory(() => HospitalViewModel());
locator.registerFactory(() => LiveCarePatientViewModel());
locator.registerFactory(() => PatientMedicalReportViewModel());
+ locator.registerFactory(() => ScanQrViewModel());
}
diff --git a/lib/main.dart b/lib/main.dart
index a95378e5..c29429b0 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -11,6 +11,7 @@ import 'package:provider/provider.dart';
import './config/size_config.dart';
import './routes.dart';
import 'config/config.dart';
+import 'core/service/NavigationService.dart';
import 'core/viewModel/authentication_view_model.dart';
import 'locator.dart';
@@ -66,6 +67,7 @@ class MyApp extends StatelessWidget {
dividerColor: Colors.grey[350],
backgroundColor: Color.fromRGBO(255, 255, 255, 1),
),
+ navigatorKey: locator().navigatorKey,
initialRoute: INIT_ROUTE,
routes: routes,
debugShowCheckedModeBanner: false,
diff --git a/lib/models/dashboard/get_special_clinical_care_List_Respose_Model.dart b/lib/models/dashboard/get_special_clinical_care_List_Respose_Model.dart
new file mode 100644
index 00000000..ec19abb0
--- /dev/null
+++ b/lib/models/dashboard/get_special_clinical_care_List_Respose_Model.dart
@@ -0,0 +1,32 @@
+class GetSpecialClinicalCareListResponseModel {
+ int projectID;
+ int clinicID;
+ String clinicDescription;
+ String clinicDescriptionN;
+ bool isActive;
+
+ GetSpecialClinicalCareListResponseModel(
+ {this.projectID,
+ this.clinicID,
+ this.clinicDescription,
+ this.clinicDescriptionN,
+ this.isActive});
+
+ GetSpecialClinicalCareListResponseModel.fromJson(Map json) {
+ projectID = json['ProjectID'];
+ clinicID = json['ClinicID'];
+ clinicDescription = json['ClinicDescription'];
+ clinicDescriptionN = json['ClinicDescriptionN'];
+ isActive = json['IsActive'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['ProjectID'] = this.projectID;
+ data['ClinicID'] = this.clinicID;
+ data['ClinicDescription'] = this.clinicDescription;
+ data['ClinicDescriptionN'] = this.clinicDescriptionN;
+ data['IsActive'] = this.isActive;
+ return data;
+ }
+}
diff --git a/lib/models/dashboard/get_special_clinical_care_mapping_List_Respose_Model.dart b/lib/models/dashboard/get_special_clinical_care_mapping_List_Respose_Model.dart
new file mode 100644
index 00000000..287f40f1
--- /dev/null
+++ b/lib/models/dashboard/get_special_clinical_care_mapping_List_Respose_Model.dart
@@ -0,0 +1,37 @@
+class GetSpecialClinicalCareMappingListResponseModel {
+ int mappingProjectID;
+ int clinicID;
+ int nursingStationID;
+ bool isActive;
+ int projectID;
+ String description;
+
+ GetSpecialClinicalCareMappingListResponseModel(
+ {this.mappingProjectID,
+ this.clinicID,
+ this.nursingStationID,
+ this.isActive,
+ this.projectID,
+ this.description});
+
+ GetSpecialClinicalCareMappingListResponseModel.fromJson(
+ Map json) {
+ mappingProjectID = json['MappingProjectID'];
+ clinicID = json['ClinicID'];
+ nursingStationID = json['NursingStationID'];
+ isActive = json['IsActive'];
+ projectID = json['ProjectID'];
+ description = json['Description'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['MappingProjectID'] = this.mappingProjectID;
+ data['ClinicID'] = this.clinicID;
+ data['NursingStationID'] = this.nursingStationID;
+ data['IsActive'] = this.isActive;
+ data['ProjectID'] = this.projectID;
+ data['Description'] = this.description;
+ return data;
+ }
+}
diff --git a/lib/models/livecare/start_call_req.dart b/lib/models/livecare/start_call_req.dart
index 9dabccc1..b3ceabb5 100644
--- a/lib/models/livecare/start_call_req.dart
+++ b/lib/models/livecare/start_call_req.dart
@@ -1,56 +1,56 @@
class StartCallReq {
- int? vCID;
- bool? isrecall;
- String? tokenID;
- String? generalid;
- int? doctorId;
- bool? isOutKsa;
- String? projectName;
- String? docotrName;
- String? clincName;
- String? docSpec;
- int? clinicId;
+ String clincName;
+ int clinicId;
+ String docSpec;
+ String docotrName;
+ int doctorId;
+ String generalid;
+ bool isOutKsa;
+ bool isrecall;
+ String projectName;
+ String tokenID;
+ int vCID;
StartCallReq(
- {this.vCID,
- this.isrecall,
- this.tokenID,
- this.generalid,
- this.doctorId,
- this.isOutKsa,
- this.projectName,
- this.docotrName,
- this.clincName,
- this.docSpec,
- this.clinicId});
+ {this.clincName,
+ this.clinicId,
+ this.docSpec,
+ this.docotrName,
+ this.doctorId,
+ this.generalid,
+ this.isOutKsa,
+ this.isrecall,
+ this.projectName,
+ this.tokenID,
+ this.vCID});
StartCallReq.fromJson(Map json) {
- vCID = json['VC_ID'];
- isrecall = json['isrecall'];
- tokenID = json['TokenID'];
- generalid = json['generalid'];
+ clincName = json['clincName'];
+ clinicId = json['ClinicId'];
+ docSpec = json['Doc_Spec'];
+ docotrName = json['DocotrName'];
doctorId = json['DoctorId'];
+ generalid = json['generalid'];
isOutKsa = json['IsOutKsa'];
+ isrecall = json['isrecall'];
projectName = json['projectName'];
- docotrName = json['DocotrName'];
- clincName = json['clincName'];
- docSpec = json['Doc_Spec'];
- clinicId = json['ClinicId'];
+ tokenID = json['TokenID'];
+ vCID = json['VC_ID'];
}
Map toJson() {
final Map data = new Map();
- data['VC_ID'] = this.vCID;
- data['isrecall'] = this.isrecall;
- data['TokenID'] = this.tokenID;
- data['generalid'] = this.generalid;
+ data['clincName'] = this.clincName;
+ data['ClinicId'] = this.clinicId;
+ data['Doc_Spec'] = this.docSpec;
+ data['DocotrName'] = this.docotrName;
data['DoctorId'] = this.doctorId;
+ data['generalid'] = this.generalid;
data['IsOutKsa'] = this.isOutKsa;
+ data['isrecall'] = this.isrecall;
data['projectName'] = this.projectName;
- data['DocotrName'] = this.docotrName;
- data['clincName'] = this.clincName;
- data['Doc_Spec'] = this.docSpec;
- data['ClinicId'] = this.clinicId;
+ data['TokenID'] = this.tokenID;
+ data['VC_ID'] = this.vCID;
return data;
}
-}
+}
\ No newline at end of file
diff --git a/lib/models/patient/my_referral/my_referred_patient_model.dart b/lib/models/patient/my_referral/my_referred_patient_model.dart
index 0dad14af..dbb3a90b 100644
--- a/lib/models/patient/my_referral/my_referred_patient_model.dart
+++ b/lib/models/patient/my_referral/my_referred_patient_model.dart
@@ -164,8 +164,9 @@ class MyReferredPatientModel {
referringDoctor = json['ReferringDoctor'];
referralClinic = json['ReferralClinic'];
referringClinic = json['ReferringClinic'];
- referralStatus = json['ReferralStatus'];
- referralDate = json['ReferralDate'];
+ createdOn = json['CreatedOn'];
+ referralStatus = json["ReferralStatus"] is String?json['ReferralStatus']== "Accepted"?46:json['ReferralStatus']=="Pending"?1:0 : json['ReferralStatus'];
+ referralDate = json['ReferralDate'] ?? createdOn;
referringDoctorRemarks = json['ReferringDoctorRemarks'];
referredDoctorRemarks = json['ReferredDoctorRemarks'];
referralResponseOn = json['ReferralResponseOn'];
@@ -177,7 +178,6 @@ class MyReferredPatientModel {
appointmentDate = json['AppointmentDate'];
appointmentType = json['AppointmentType'];
patientMRN = json['PatientMRN'];
- createdOn = json['CreatedOn'];
clinicID = json['ClinicID'];
nationalityID = json['NationalityID'];
age = json['Age'];
diff --git a/lib/models/patient/profile/patient_profile_app_bar_model.dart b/lib/models/patient/profile/patient_profile_app_bar_model.dart
new file mode 100644
index 00000000..f4654a29
--- /dev/null
+++ b/lib/models/patient/profile/patient_profile_app_bar_model.dart
@@ -0,0 +1,86 @@
+import '../patiant_info_model.dart';
+
+class PatientProfileAppBarModel {
+ double height;
+ bool isInpatient;
+ bool isDischargedPatient;
+ bool isFromLiveCare;
+ PatiantInformtion patient;
+ String doctorName;
+ String branch;
+ DateTime appointmentDate;
+ String profileUrl;
+ String invoiceNO;
+ String orderNo;
+ bool isPrescriptions;
+ bool isMedicalFile;
+ String episode;
+ String visitDate;
+ String clinic;
+ bool isAppointmentHeader;
+ bool isFromLabResult;
+
+ PatientProfileAppBarModel(
+ {this.height = 0.0,
+ this.isInpatient= false,
+ this.isDischargedPatient= false,
+ this.isFromLiveCare= false,
+ this.patient,
+ this.doctorName,
+ this.branch,
+ this.appointmentDate,
+ this.profileUrl,
+ this.invoiceNO,
+ this.orderNo,
+ this.isPrescriptions= false,
+ this.isMedicalFile= false,
+ this.episode,
+ this.visitDate,
+ this.clinic,
+ this.isAppointmentHeader = false,
+ this.isFromLabResult =false});
+
+ PatientProfileAppBarModel.fromJson(Map json) {
+ height = json['height'];
+ isInpatient = json['isInpatient'];
+ isDischargedPatient = json['isDischargedPatient'];
+ isFromLiveCare = json['isFromLiveCare'];
+ patient = json['patient'];
+ doctorName = json['doctorName'];
+ branch = json['branch'];
+ appointmentDate = json['appointmentDate'];
+ profileUrl = json['profileUrl'];
+ invoiceNO = json['invoiceNO'];
+ orderNo = json['orderNo'];
+ isPrescriptions = json['isPrescriptions'];
+ isMedicalFile = json['isMedicalFile'];
+ episode = json['episode'];
+ visitDate = json['visitDate'];
+ clinic = json['clinic'];
+ isAppointmentHeader = json['isAppointmentHeader'];
+ isFromLabResult = json['isFromLabResult'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['height'] = this.height;
+ data['isInpatient'] = this.isInpatient;
+ data['isDischargedPatient'] = this.isDischargedPatient;
+ data['isFromLiveCare'] = this.isFromLiveCare;
+ data['patient'] = this.patient;
+ data['doctorName'] = this.doctorName;
+ data['branch'] = this.branch;
+ data['appointmentDate'] = this.appointmentDate;
+ data['profileUrl'] = this.profileUrl;
+ data['invoiceNO'] = this.invoiceNO;
+ data['orderNo'] = this.orderNo;
+ data['isPrescriptions'] = this.isPrescriptions;
+ data['isMedicalFile'] = this.isMedicalFile;
+ data['episode'] = this.episode;
+ data['visitDate'] = this.visitDate;
+ data['clinic'] = this.clinic;
+ data['isAppointmentHeader'] = this.isAppointmentHeader;
+ data['isFromLabResult'] = this.isFromLabResult;
+ return data;
+ }
+}
diff --git a/lib/root_page.dart b/lib/root_page.dart
index 6b5eb09d..f7955eff 100644
--- a/lib/root_page.dart
+++ b/lib/root_page.dart
@@ -11,8 +11,11 @@ import 'landing_page.dart';
class RootPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
+
+
AuthenticationViewModel authenticationViewModel = Provider.of(context);
Widget buildRoot() {
+
switch (authenticationViewModel.status) {
case APP_STATUS.LOADING:
return Scaffold(
diff --git a/lib/routes.dart b/lib/routes.dart
index 33aa5636..0826c76e 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -1,4 +1,5 @@
import 'package:doctor_app_flutter/root_page.dart';
+import 'package:doctor_app_flutter/screens/live_care/end_call_screen.dart';
import 'package:doctor_app_flutter/screens/medical-file/health_summary_page.dart';
import 'package:doctor_app_flutter/screens/patients/ECGPage.dart';
import 'package:doctor_app_flutter/screens/patients/insurance_approval_screen_patient.dart';
@@ -37,6 +38,7 @@ const String LOGIN = 'login';
const String VERIFICATION_METHODS = 'verification-methods';
const String PATIENTS = 'patients/patients';
const String PATIENTS_PROFILE = 'patients/patients-profile';
+const String PATIENTS_END_Call = 'patients/patients-profile/endCall';
const String IN_PATIENTS_PROFILE = 'inpatients/patients-profile';
const String LAB_RESULT = 'patients/lab_result';
const String HEALTH_SUMMARY = 'patients/health-summary';
@@ -88,6 +90,7 @@ var routes = {
PATIENT_MEDICAL_REPORT: (_) => MedicalReportPage(),
PATIENT_MEDICAL_REPORT_INSERT: (_) => AddVerifyMedicalReport(),
PATIENT_MEDICAL_REPORT_DETAIL: (_) => MedicalReportDetailPage(),
+ PATIENTS_END_Call: (_) => EndCallScreen(),
CREATE_EPISODE: (_) => UpdateSoapIndex(
isUpdate: true,
),
diff --git a/lib/screens/auth/login_screen.dart b/lib/screens/auth/login_screen.dart
index e6d024fd..6adbbfe0 100644
--- a/lib/screens/auth/login_screen.dart
+++ b/lib/screens/auth/login_screen.dart
@@ -2,14 +2,11 @@ import 'package:doctor_app_flutter/config/size_config.dart';
import 'package:doctor_app_flutter/core/enum/viewstate.dart';
import 'package:doctor_app_flutter/core/model/hospitals/get_hospitals_response_model.dart';
import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart';
-import 'package:doctor_app_flutter/screens/auth/verification_methods_screen.dart';
import 'package:doctor_app_flutter/util/helpers.dart';
import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
-import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart';
import 'package:doctor_app_flutter/widgets/shared/text_fields/app-textfield-custom.dart';
-import 'package:doctor_app_flutter/widgets/shared/text_fields/app_text_form_field.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:provider/provider.dart';
@@ -25,7 +22,6 @@ class _LoginScreenState extends State {
late String platformImei;
bool allowCallApi = true;
- //TODO change AppTextFormField to AppTextFormFieldCustom
final loginFormKey = GlobalKey();
var projectIdController = TextEditingController();
var userIdController = TextEditingController();
@@ -38,134 +34,137 @@ class _LoginScreenState extends State {
@override
Widget build(BuildContext context) {
authenticationViewModel = Provider.of(context);
+ double textFieldHeight = SizeConfig.heightMultiplier * (SizeConfig.isHeightVeryShort ?10:SizeConfig.isHeightShort?8:6);
return AppScaffold(
isShowAppBar: false,
backgroundColor: HexColor('#F8F8F8'),
- body: SafeArea(
- child: ListView(children: [
- Container(
+ body: SingleChildScrollView(
+ child: SafeArea(
+ child: Container(
margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 30),
alignment: Alignment.topLeft,
- child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- //TODO Use App Text rather than text
- Container(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Column(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ //TODO Use App Text rather than text
+ Container(
+ child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
- children: [
+ children: [
SizedBox(
- height: 30,
+ height: 10,
),
- ],
- ),
- Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
- SizedBox(
- height: 10,
- ),
- Text(
- TranslationBase.of(context).welcomeTo ?? "",
- style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, fontFamily: 'Poppins'),
+ Text(
+ TranslationBase.of(context).welcomeTo,
+ style: TextStyle(
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 4,
+ fontWeight: FontWeight.w600,
+ fontFamily: 'Poppins'),
+ ),
+ Text(
+ TranslationBase.of(context).drSulaimanAlHabib,
+ style: TextStyle(
+ color: Color(0xFF2B353E),
+ fontWeight: FontWeight.bold,
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 6,
+ fontFamily: 'Poppins'),
+ ),
+ Text(
+ "Doctor App",
+ style: TextStyle(
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 4,
+ fontWeight: FontWeight.w600,
+ color: Color(0xFFD02127)),
+ ),
+ ])),
+ SizedBox(
+ height: 40,
+ ),
+ Form(
+ key: loginFormKey,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ buildSizedBox(),
+ AppTextFieldCustom(
+ height: textFieldHeight,
+ hintText: TranslationBase.of(context).enterId,
+ hasBorder: true,
+ controller: userIdController,
+ onChanged: (value) {
+ if (value != null)
+ setState(() {
+ authenticationViewModel.userInfo.userID =
+ value.trim();
+ });
+ },
),
- Text(
- TranslationBase.of(context).drSulaimanAlHabib ?? "",
- style: TextStyle(
- color: Color(0xFF2B353E),
- fontWeight: FontWeight.bold,
- fontSize: SizeConfig.isMobile ? 24 : SizeConfig.realScreenWidth * 0.029,
- fontFamily: 'Poppins'),
+ buildSizedBox(),
+ AppTextFieldCustom(
+ height: textFieldHeight,
+ hintText: TranslationBase.of(context).enterPassword,
+ hasBorder: true,
+ isSecure: true,
+ controller: passwordController,
+ onChanged: (value) {
+ if (value != null)
+ setState(() {
+ authenticationViewModel.userInfo.password =
+ value.trim();
+ });
+ this.getProjects(
+ authenticationViewModel.userInfo.userID);
+ },
+ onClick: () {},
),
- Text(
- "Doctor App",
- style: TextStyle(
- fontSize: SizeConfig.isMobile ? 16 : SizeConfig.realScreenWidth * 0.030,
- fontWeight: FontWeight.w600,
- color: Color(0xFFD02127)),
+ buildSizedBox(),
+ AppTextFieldCustom(
+ height: textFieldHeight,
+ hintText:
+ TranslationBase.of(context).selectYourProject,
+ hasBorder: true,
+ controller: projectIdController,
+ isTextFieldHasSuffix: true,
+ enabled: false,
+ onClick: projectsList.isEmpty== null ? null:() {
+ Helpers.showCupertinoPicker(
+ context,
+ projectsList,
+ 'facilityName',
+ onSelectProject,
+ authenticationViewModel);
+ },
),
+ buildSizedBox(),
]),
- ],
- )),
- SizedBox(
- height: 40,
- ),
- Form(
- key: loginFormKey,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Container(
- width: SizeConfig.realScreenWidth * 0.90,
- height: SizeConfig.realScreenHeight * 0.65,
- child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
- buildSizedBox(),
- AppTextFieldCustom(
- hintText: TranslationBase.of(context).enterId,
- hasBorder: true,
- controller: userIdController,
- onChanged: (value) {
- if (value != null)
- setState(() {
- authenticationViewModel.userInfo.userID = value.trim();
- });
- },
- ),
- buildSizedBox(),
- AppTextFieldCustom(
- hintText: TranslationBase.of(context).enterPassword,
- hasBorder: true,
- isSecure: true,
- controller: passwordController,
- onChanged: (value) {
- if (value != null)
- setState(() {
- authenticationViewModel.userInfo.password = value.trim();
- });
- // if(allowCallApi) {
- this.getProjects(authenticationViewModel.userInfo.userID);
- // setState(() {
- // allowCallApi = false;
- // });
- // }
- },
- onClick: () {},
- ),
- buildSizedBox(),
- AppTextFieldCustom(
- hintText: TranslationBase.of(context).selectYourProject,
- hasBorder: true,
- controller: projectIdController,
- isTextFieldHasSuffix: true,
- enabled: false,
- onClick: () {
- Helpers.showCupertinoPicker(
- context, projectsList, 'facilityName', onSelectProject, authenticationViewModel);
- },
- ),
- buildSizedBox()
- ]),
- ),
- ],
- ),
- )
- ],
- )
- ]))
- ]),
+ ),
+ SizedBox(
+ height: 40,
+ ),
+ ],
+ )),
+ ),
),
bottomSheet: Container(
- height: 90,
+// color: Colors.green,
+ height: SizeConfig.heightMultiplier * 10,
width: double.infinity,
child: Center(
child: FractionallySizedBox(
widthFactor: 0.9,
child: Column(
- mainAxisAlignment: MainAxisAlignment.end,
+ mainAxisAlignment: MainAxisAlignment.center,
children: [
AppButton(
+ height: SizeConfig.heightMultiplier *
+ (SizeConfig.isHeightVeryShort ? 8 : 6),
+ hPadding: 1,
title: TranslationBase.of(context).login,
color: Color(0xFFD02127),
fontWeight: FontWeight.w700,
@@ -175,9 +174,7 @@ class _LoginScreenState extends State {
login(context);
},
),
- SizedBox(
- height: 25,
- )
+
],
),
),
@@ -188,7 +185,7 @@ class _LoginScreenState extends State {
SizedBox buildSizedBox() {
return SizedBox(
- height: 20,
+ height: SizeConfig.heightMultiplier * 2,
);
}
@@ -205,22 +202,14 @@ class _LoginScreenState extends State {
} else {
GifLoaderDialogUtils.hideDialog(context);
authenticationViewModel.setUnverified(true, isFromLogin: true);
- // Navigator.of(context).pushReplacement(
- // MaterialPageRoute(
- // builder: (BuildContext context) =>
- // VerificationMethodsScreen(
- // password: authenticationViewModel.userInfo.password,
- // isFromLogin: true,
- // ),
- // ),
- // );
}
}
}
onSelectProject(index) {
setState(() {
- authenticationViewModel.userInfo.projectID = projectsList[index].facilityId;
+ authenticationViewModel.userInfo.projectID =
+ projectsList[index].facilityId;
projectIdController.text = projectsList[index].facilityName!;
});
@@ -236,7 +225,8 @@ class _LoginScreenState extends State {
if (authenticationViewModel.state == ViewState.Idle) {
projectsList = authenticationViewModel.hospitals;
setState(() {
- authenticationViewModel.userInfo.projectID = projectsList[0].facilityId;
+ authenticationViewModel.userInfo.projectID =
+ projectsList[0].facilityId;
projectIdController.text = projectsList[0].facilityName!;
});
}
diff --git a/lib/screens/auth/verification_methods_screen.dart b/lib/screens/auth/verification_methods_screen.dart
index 03d6a6e6..f211781f 100644
--- a/lib/screens/auth/verification_methods_screen.dart
+++ b/lib/screens/auth/verification_methods_screen.dart
@@ -1,6 +1,5 @@
import 'dart:io' show Platform;
-import 'package:doctor_app_flutter/config/config.dart';
import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
import 'package:doctor_app_flutter/core/enum/auth_method_types.dart';
import 'package:doctor_app_flutter/core/enum/viewstate.dart';
@@ -13,21 +12,15 @@ import 'package:doctor_app_flutter/widgets/shared/app_loader_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dart';
-import 'package:doctor_app_flutter/widgets/shared/buttons/secondary_button.dart';
import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart';
-import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:provider/provider.dart';
import '../../config/size_config.dart';
-import '../../landing_page.dart';
-import '../../root_page.dart';
-import '../../routes.dart';
import '../../util/dr_app_shared_pref.dart';
import '../../util/helpers.dart';
import '../../widgets/auth/verification_methods_list.dart';
-import 'login_screen.dart';
DrAppSharedPreferances sharedPref = new DrAppSharedPreferances();
Helpers helpers = Helpers();
@@ -63,303 +56,390 @@ class _VerificationMethodsScreenState extends State {
body: SingleChildScrollView(
child: Center(
child: FractionallySizedBox(
- child: Container(
- margin: EdgeInsetsDirectional.fromSTEB(30, 0, 30, 0),
- height: SizeConfig.realScreenHeight * .95,
- width: SizeConfig.realScreenWidth,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- // mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- SizedBox(
- height: 80,
- ),
- if (authenticationViewModel.isFromLogin)
- InkWell(
- onTap: () {
- authenticationViewModel.setUnverified(false, isFromLogin: false);
- authenticationViewModel.setAppStatus(APP_STATUS.UNAUTHENTICATED);
- },
- child: Icon(
- Icons.arrow_back_ios,
- color: Color(0xFF2B353E),
- )),
- Container(
- child: Column(
+ widthFactor: 0.9,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ height: SizeConfig.heightMultiplier * (SizeConfig.isHeightVeryShort?6:4),
+ ),
+ if(authenticationViewModel.isFromLogin)
+ InkWell(
+ onTap: (){
+ authenticationViewModel.setUnverified(false,isFromLogin: false);
+ authenticationViewModel.setAppStatus(APP_STATUS.UNAUTHENTICATED);
+ },
+ child: Icon(Icons.arrow_back_ios,color: Color(0xFF2B353E),)
+
+ ),
+ Column(
+ children: [
+ SizedBox(
+ height: SizeConfig.heightMultiplier*(SizeConfig.isHeightVeryShort?3:4),
+ ),
+ authenticationViewModel.user != null && isMoreOption == false
+ ? Column(
+ mainAxisAlignment:
+ MainAxisAlignment.spaceEvenly,
+ crossAxisAlignment: CrossAxisAlignment.start,
children: [
+
+ AppText(
+ TranslationBase.of(context).welcomeBack,
+ fontSize:SizeConfig.getTextMultiplierBasedOnWidth()*4,
+ fontWeight: FontWeight.w700,
+ color: Color(0xFF2B353E),
+ ),
+ AppText(
+ Helpers.capitalize(authenticationViewModel.user.doctorName),
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth()*6,
+ color: Color(0xFF2B353E),
+ fontWeight: FontWeight.bold,
+ ),
SizedBox(
- height: 20,
+ height: SizeConfig.heightMultiplier*4,
),
- authenticationViewModel.user != null && isMoreOption == false
- ? Column(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AppText(
- TranslationBase.of(context).welcomeBack,
- fontSize: 12,
- fontWeight: FontWeight.w700,
- color: Color(0xFF2B353E),
- ),
- AppText(
- Helpers.capitalize(authenticationViewModel.user?.doctorName),
- fontSize: 24,
- color: Color(0xFF2B353E),
- fontWeight: FontWeight.bold,
- ),
- SizedBox(
- height: 20,
- ),
- AppText(
- TranslationBase.of(context).accountInfo,
- fontSize: 16,
- color: Color(0xFF2E303A),
- fontWeight: FontWeight.w600,
- ),
- SizedBox(
- height: 20,
- ),
- Container(
- padding: EdgeInsets.all(15),
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.all(
- Radius.circular(10),
- ),
- border: Border.all(color: HexColor('#707070'), width: 0.1),
- ),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Column(
- children: [
- Text(
- TranslationBase.of(context).lastLoginAt!,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- fontFamily: 'Poppins',
- fontSize: 16,
- color: Color(0xFF2E303A),
- fontWeight: FontWeight.w700,
- ),
- ),
- Row(
- children: [
- AppText(
- TranslationBase.of(context).verifyWith,
- fontSize: 14,
- color: Color(0xFF575757),
- fontWeight: FontWeight.w600,
- ),
- AppText(
- authenticationViewModel.getType(
- authenticationViewModel.user?.logInTypeID, context),
- fontSize: 14,
- color: Color(0xFF2B353E),
- fontWeight: FontWeight.w700,
- ),
- ],
- )
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- ),
- Column(
- children: [
- AppText(
- authenticationViewModel.user?.editedOn != null
- ? AppDateUtils.getDayMonthYearDateFormatted(
- AppDateUtils.convertStringToDate(
- authenticationViewModel.user!.editedOn ?? ""))
- : authenticationViewModel.user?.createdOn != null
- ? AppDateUtils.getDayMonthYearDateFormatted(
- AppDateUtils.convertStringToDate(
- authenticationViewModel.user!.createdOn ?? ""))
- : '--',
- textAlign: TextAlign.right,
- fontSize: 13,
+ AppText(
+ TranslationBase.of(context).accountInfo ,
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth()*5,
+ color: Color(0xFF2E303A),
+ fontWeight: FontWeight.w600,
+ ),
+ SizedBox(
+ height: SizeConfig.heightMultiplier*4
+ ),
+ Container(
+ padding: EdgeInsets.all(15),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.all(
+ Radius.circular(10),
+ ),
+ border: Border.all(
+ color: HexColor('#707070'),
+ width: 0.1),
+ ),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ width: SizeConfig.realScreenWidth * .5,
+ padding: EdgeInsets.all(0),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Text(
+ TranslationBase.of(context)
+ .lastLoginAt,
+ overflow: TextOverflow.ellipsis,
+ style: TextStyle(
+ fontFamily: 'Poppins',
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 4.5,
color: Color(0xFF2E303A),
fontWeight: FontWeight.w700,
),
- AppText(
- authenticationViewModel.user?.editedOn != null
- ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(
- authenticationViewModel!.user!.editedOn ?? ""))
- : authenticationViewModel.user!.createdOn != null
- ? AppDateUtils.getHour(AppDateUtils.convertStringToDate(
- authenticationViewModel.user!.createdOn ?? ""))
- : '--',
- textAlign: TextAlign.right,
- fontSize: 14,
- fontWeight: FontWeight.w600,
- color: Color(0xFF575757),
- )
- ],
- crossAxisAlignment: CrossAxisAlignment.start,
- )
- ],
- ),
- ),
- SizedBox(
- height: 20,
- ),
- Row(
- children: [
- AppText(
- "Please Verify",
- fontSize: 16,
- color: Color(0xFF2B353E),
- fontWeight: FontWeight.w700,
- ),
- ],
- )
- ],
- )
- : Column(
- mainAxisAlignment: MainAxisAlignment.spaceEvenly,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- this.onlySMSBox == false
- ? Container(
- margin: EdgeInsets.only(bottom: 20, top: 30),
- child: AppText(
- TranslationBase.of(context).verifyLoginWith,
- fontSize: 18,
- color: Color(0xFF2E303A),
- fontWeight: FontWeight.bold,
- textAlign: TextAlign.left,
+ ),
+ Container(
+ width: MediaQuery.of(context)
+ .size
+ .width *
+ 0.55,
+ child: RichText(
+ text: TextSpan(
+ text: TranslationBase.of(context).verifyWith,
+ style: TextStyle(
+ color: Color(0xFF2B353E),
+ fontWeight: FontWeight.w600,
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 4.5,
+ fontFamily: 'Poppins',
+ ),
+ children: [
+ TextSpan(
+ text: authenticationViewModel
+ .getType(
+ authenticationViewModel
+ .user
+ .logInTypeID,
+ context),
+ style: TextStyle(
+ color:
+ Color(0xFF2B353E),
+ fontSize: SizeConfig
+ .getTextMultiplierBasedOnWidth() *
+ 4.5,
+ fontFamily: 'Poppins',
+ fontWeight:
+ FontWeight.w700,
+ ),
+ )
+ ]),
),
- )
- : AppText(
- TranslationBase.of(context).verifyFingerprint2,
- fontSize: SizeConfig.textMultiplier * 2.5,
- textAlign: TextAlign.start,
),
- ]),
- authenticationViewModel.user != null && isMoreOption == false
- ? Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(mainAxisAlignment: MainAxisAlignment.center, children: [
- Expanded(
- child: InkWell(
- onTap: () => {
- // TODO check this logic it seem it will create bug to us
- authenticateUser(AuthMethodTypes.Fingerprint, true)
- },
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: SelectedAuthMethodTypesService.getMethodsTypeService(
- authenticationViewModel.user!.logInTypeID!),
- authenticateUser: (AuthMethodTypes authMethodType, isActive) =>
- authenticateUser(authMethodType, isActive),
- )),
+ ],
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
),
- Expanded(
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: AuthMethodTypes.MoreOptions,
- onShowMore: () {
- setState(() {
- isMoreOption = true;
- });
- },
- ))
- ]),
- ])
- : Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- onlySMSBox == false
- ? Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Expanded(
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: AuthMethodTypes.Fingerprint,
- authenticateUser: (AuthMethodTypes authMethodType, isActive) =>
- authenticateUser(authMethodType, isActive),
- )),
- Expanded(
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: AuthMethodTypes.FaceID,
- authenticateUser: (AuthMethodTypes authMethodType, isActive) =>
- authenticateUser(authMethodType, isActive),
- ))
- ],
- )
- : SizedBox(),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Expanded(
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: AuthMethodTypes.SMS,
- authenticateUser: (AuthMethodTypes authMethodType, isActive) =>
- authenticateUser(authMethodType, isActive),
- )),
- Expanded(
- child: VerificationMethodsList(
- authenticationViewModel: authenticationViewModel,
- authMethodType: AuthMethodTypes.WhatsApp,
- authenticateUser: (AuthMethodTypes authMethodType, isActive) =>
- authenticateUser(authMethodType, isActive),
- ))
- ],
),
- ]),
+ Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+
+ children: [
+ AppText(
+ authenticationViewModel
+ .user.editedOn !=
+ null
+ ? AppDateUtils
+ .getDayMonthYearDateFormatted(
+ AppDateUtils
+ .convertStringToDate(
+ authenticationViewModel
+ .user
+ .editedOn))
+ : authenticationViewModel
+ .user.createdOn !=
+ null
+ ? AppDateUtils.getDayMonthYearDateFormatted(
+ AppDateUtils.convertStringToDate(authenticationViewModel.user
+ .createdOn))
+ : '--',
+ textAlign:
+ TextAlign.right,
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth() *4.5,
+ color: Color(0xFF2E303A),
+ fontWeight: FontWeight.w700,
+ ),
+ AppText(
+ authenticationViewModel.user.editedOn !=
+ null
+ ? AppDateUtils.getHour(
+ AppDateUtils.convertStringToDate(
+ authenticationViewModel.user
+ .editedOn))
+ : authenticationViewModel.user.createdOn !=
+ null
+ ? AppDateUtils.getHour(
+ AppDateUtils.convertStringToDate(authenticationViewModel.user
+ .createdOn))
+ : '--',
+ textAlign:
+ TextAlign.right,
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth() *4.5,
+ fontWeight: FontWeight.w600,
+ color: Color(0xFF575757),
+ )
+ ],
+ crossAxisAlignment: CrossAxisAlignment.start,
+
+ )
+ ],
+ ),
+ ),
+ SizedBox(
+ height: SizeConfig.heightMultiplier*3,
+ ),
- // )
+ Row(
+ children: [
+
+ //todo add translation
+ AppText(
+ "Please Verify",
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth() * 5,
+ color: Color(0xFF2B353E),
+
+ fontWeight: FontWeight.w700,
+ ),
+ ],
+ ),
+ SizedBox(
+ height: SizeConfig.heightMultiplier*2,
+ ),
],
- ),
- ),
- ],
- ),
+ )
+ : Column(
+ mainAxisAlignment:
+ MainAxisAlignment.spaceEvenly,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ this.onlySMSBox == false
+ ? Container(
+ margin: EdgeInsets.only(bottom: 20, top: 30),
+ child: AppText(
+ TranslationBase.of(context)
+ .verifyLoginWith ,
+ fontSize: SizeConfig.getTextMultiplierBasedOnWidth()* 4 ,
+ color: Color(0xFF2E303A),
+ fontWeight: FontWeight.bold,
+ textAlign: TextAlign.left,
+ ),
+ )
+ : AppText(
+ TranslationBase.of(context)
+ .verifyFingerprint2,
+ fontSize:
+ SizeConfig.getTextMultiplierBasedOnWidth()* 4,
+ textAlign: TextAlign.start,
+ ),
+ ]),
+ authenticationViewModel.user != null && isMoreOption == false
+ ? Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ Expanded(
+ child: InkWell(
+ onTap: () =>
+ {
+ // TODO check this logic it seem it will create bug to us
+ authenticateUser(
+ AuthMethodTypes
+ .Fingerprint, true)
+ },
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType: SelectedAuthMethodTypesService
+ .getMethodsTypeService(
+ authenticationViewModel.user
+ .logInTypeID),
+ authenticateUser:
+ (AuthMethodTypes
+ authMethodType,
+ isActive) =>
+ authenticateUser(
+ authMethodType,
+ isActive),
+ )),
+ ),
+ Expanded(
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType:
+ AuthMethodTypes.MoreOptions,
+ onShowMore: () {
+ setState(() {
+ isMoreOption = true;
+ });
+ },
+ ))
+ ]),
+ ])
+ : Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ onlySMSBox == false
+ ? Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ Expanded(
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType:
+ AuthMethodTypes.Fingerprint,
+ authenticateUser:
+ (AuthMethodTypes
+ authMethodType,
+ isActive) =>
+ authenticateUser(
+ authMethodType,
+ isActive),
+ )),
+ Expanded(
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType:
+ AuthMethodTypes.FaceID,
+ authenticateUser:
+ (AuthMethodTypes
+ authMethodType,
+ isActive) =>
+ authenticateUser(
+ authMethodType,
+ isActive),
+ ))
+ ],
+ )
+ : SizedBox(),
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ Expanded(
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType: AuthMethodTypes
+ .SMS,
+ authenticateUser:
+ (
+ AuthMethodTypes authMethodType,
+ isActive) =>
+ authenticateUser(
+ authMethodType, isActive),
+ )),
+ Expanded(
+ child: VerificationMethodsList(
+ authenticationViewModel:authenticationViewModel,
+ authMethodType:
+ AuthMethodTypes.WhatsApp,
+ authenticateUser:
+ (
+ AuthMethodTypes authMethodType,
+ isActive) =>
+ authenticateUser(
+ authMethodType, isActive),
+ ))
+ ],
+ ),
+ ]),
+
+ // )
+ ],
+ ),
+ ],
),
),
),
),
- bottomSheet: authenticationViewModel.user == null
- ? SizedBox(
- height: 0,
- )
- : Container(
- height: 90,
- width: double.infinity,
- child: Center(
- child: FractionallySizedBox(
- widthFactor: 0.9,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- SecondaryButton(
- label: TranslationBase.of(context).useAnotherAccount!,
- color: Color(0xFFD02127),
- //fontWeight: FontWeight.w700,
- onTap: () {
- authenticationViewModel.deleteUser();
- authenticationViewModel.setAppStatus(APP_STATUS.UNAUTHENTICATED);
- // Navigator.pushAndRemoveUntil(
- // AppGlobal.CONTEX,
- // FadePage(
- // page: RootPage(),
- // ),
- // (r) => false);
- // Navigator.of(context).pushNamed(LOGIN);
- },
- ),
- SizedBox(
- height: 25,
- )
- ],
- ),
+ bottomSheet: authenticationViewModel.user == null ? SizedBox(height: 0,) : Container(
+ // color: Colors.green,
+ height: SizeConfig.heightMultiplier * 10 ,
+ width: double.infinity,
+ child: Center(
+ child: FractionallySizedBox(
+ widthFactor: 0.9,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ AppButton(
+ title: TranslationBase
+ .of(context)
+ .useAnotherAccount,
+ color: Color(0xFFD02127),
+
+ fontWeight: FontWeight.w700,
+ height: SizeConfig.heightMultiplier * (SizeConfig.isHeightVeryShort? 8 : 6),
+ hPadding: 1,
+
+ onPressed: () {
+ authenticationViewModel.deleteUser();
+ authenticationViewModel.setAppStatus(APP_STATUS.UNAUTHENTICATED);
+ },
),
- ),
+
+ ],
),
+ ),
+ ),),
);
}
diff --git a/lib/screens/home/dashboard_referral_patient.dart b/lib/screens/home/dashboard_referral_patient.dart
new file mode 100644
index 00000000..0b9e6765
--- /dev/null
+++ b/lib/screens/home/dashboard_referral_patient.dart
@@ -0,0 +1,195 @@
+
+import 'package:charts_flutter/flutter.dart' as charts;
+import 'package:doctor_app_flutter/config/size_config.dart';
+import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart';
+import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
+import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
+import 'package:doctor_app_flutter/widgets/dashboard/guage_chart.dart';
+import 'package:doctor_app_flutter/widgets/dashboard/row_count.dart';
+import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
+import 'package:doctor_app_flutter/widgets/shared/rounded_container_widget.dart';
+import 'package:flutter/material.dart';
+
+import 'label.dart';
+
+class DashboardReferralPatient extends StatelessWidget {
+ final List dashboardItemList;
+ final double height;
+ final DashboardViewModel model;
+
+ const DashboardReferralPatient({Key key, this.dashboardItemList, this.height, this.model}) : super(key: key);
+ @override
+ Widget build(BuildContext context) {
+ return RoundedContainer(
+ raduis: 16,
+ showBorder: false,
+ borderColor: Colors.white,
+ shadowWidth: 0.2,
+ shadowSpreadRadius: 3,
+ shadowDy: 1,
+ margin: EdgeInsets.only(top: 15, bottom: 15, left: 10, right: 10),
+ child:
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+
+ children: [
+ Expanded(
+ flex: 1,
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+
+ children: [
+ Expanded(
+ flex: 4,
+ child: Padding(
+ padding: const EdgeInsets.all(5.0),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: EdgeInsets.all(8),
+ child: Column(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ SizedBox(
+ height: SizeConfig
+ .getHeightMultiplier(
+ height: height) *
+ (SizeConfig.isHeightVeryShort
+ ? 3
+ : SizeConfig.isHeightShort
+ ? 2
+ : 2)
+ ),
+ Label(firstLine: TranslationBase
+ .of(context)
+ .patients,
+ secondLine: TranslationBase
+ .of(context)
+ .referral,
+ color: Color(0xFF2B353E),
+ secondLineFontSize: SizeConfig
+ .getHeightMultiplier(
+ height: height) *
+ (SizeConfig.isHeightVeryShort
+ ? 5
+ : SizeConfig.isHeightShort
+ ? 7
+ : 12),),
+
+ SizedBox(
+ height: SizeConfig
+ .getHeightMultiplier(
+ height: height) *
+ (SizeConfig.isHeightVeryShort
+ ? 5
+ : SizeConfig.isHeightShort
+ ? 10
+ : 5)
+ )
+ ],
+ ),),
+ Expanded(
+ flex: 1,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ RowCounts(
+ dashboardItemList[2]
+ .summaryoptions[0]
+ .kPIParameter,
+ dashboardItemList[2]
+ .summaryoptions[0]
+ .value,
+ Colors.black, height: height,),
+ RowCounts(
+ dashboardItemList[2]
+ .summaryoptions[1]
+ .kPIParameter,
+ dashboardItemList[2]
+ .summaryoptions[1]
+ .value,
+ Colors.grey, height: height,),
+ RowCounts(
+
+ dashboardItemList[2]
+ .summaryoptions[2]
+ .kPIParameter,
+ dashboardItemList[2]
+ .summaryoptions[2]
+ .value,
+ Colors.red, height: height,),
+ ],
+ ),
+ )
+ ],
+ )),
+ ),
+ Expanded(
+ flex: 3,
+ child: Stack(children: [
+ Container(
+ padding:EdgeInsets.all(0),
+
+ child: GaugeChart(
+ _createReferralData(dashboardItemList))),
+ Positioned(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ AppText(
+ model
+ .getPatientCount(dashboardItemList[2])
+ .toString(),
+ fontSize: SizeConfig.textMultiplier * 3.0,
+ fontWeight: FontWeight.bold,
+ )
+ ],
+ ),
+ top: height * (SizeConfig.isHeightVeryShort?0.35:0.40),
+ left: 0,
+ right: 0)
+ ]),
+ ),
+ ],
+ )),
+ ]));
+ }
+ static List> _createReferralData(List dashboardItemList) {
+ final data = [
+ new GaugeSegment(
+ dashboardItemList[2].summaryoptions[0].kPIParameter,
+ getValue(dashboardItemList[1].summaryoptions[0].value),
+ charts.MaterialPalette.black),
+ new GaugeSegment(
+ dashboardItemList[2].summaryoptions[1].kPIParameter,
+ getValue(dashboardItemList[1].summaryoptions[1].value),
+ charts.MaterialPalette.gray.shadeDefault),
+ new GaugeSegment(
+ dashboardItemList[2].summaryoptions[2].kPIParameter,
+ getValue(dashboardItemList[1].summaryoptions[2].value),
+ charts.MaterialPalette.red.shadeDefault),
+ ];
+
+ return [
+ new charts.Series(
+ id: 'Segments',
+ domainFn: (GaugeSegment segment, _) => segment.segment,
+ measureFn: (GaugeSegment segment, _) => segment.size,
+ data: data,
+ colorFn: (GaugeSegment segment, _) => segment.color,
+ )
+ ];
+ }
+
+ static int getValue(value) {
+ return value == 0 ? 1 : value;
+ }
+
+}
\ No newline at end of file
diff --git a/lib/screens/home/dashboard_slider-item-widget.dart b/lib/screens/home/dashboard_slider-item-widget.dart
index 92089f4c..0d1a0e73 100644
--- a/lib/screens/home/dashboard_slider-item-widget.dart
+++ b/lib/screens/home/dashboard_slider-item-widget.dart
@@ -1,9 +1,11 @@
import 'package:doctor_app_flutter/config/size_config.dart';
import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
-import 'package:doctor_app_flutter/widgets/dashboard/activity_button.dart';
-import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
+import 'package:doctor_app_flutter/util/helpers.dart';
+import 'package:doctor_app_flutter/widgets/dashboard/activity_card.dart';
import 'package:flutter/material.dart';
+import 'label.dart';
+
class DashboardSliderItemWidget extends StatelessWidget {
final DashboardModel item;
@@ -13,22 +15,22 @@ class DashboardSliderItemWidget extends StatelessWidget {
Widget build(BuildContext context) {
return Column(
children: [
- Row(
+ Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
- AppText(
- item.kPIName,
- fontSize: SizeConfig.textMultiplier * 2.2,
- fontWeight: FontWeight.bold,
- ),
+ Label(firstLine:Helpers.getLabelFromKPI(item.kPIName) ,secondLine:Helpers.getNameFromKPI(item.kPIName), ),
+
],
),
- new Container(
- height: 110,
+
+
+
+ new Container(
+ height: SizeConfig.heightMultiplier* (SizeConfig.isHeightVeryShort?16:SizeConfig.isHeightShort?14:SizeConfig.isHeightLarge?15:13),
child: ListView(
scrollDirection: Axis.horizontal,
children: List.generate(item.summaryoptions!.length, (int index) {
- return GetActivityButton(item.summaryoptions![index]);
+ return GetActivityCard(item.summaryoptions![index]);
})))
],
);
diff --git a/lib/screens/home/dashboard_swipe_widget.dart b/lib/screens/home/dashboard_swipe_widget.dart
index 2e7815ba..5e45c9b4 100644
--- a/lib/screens/home/dashboard_swipe_widget.dart
+++ b/lib/screens/home/dashboard_swipe_widget.dart
@@ -1,16 +1,13 @@
import 'package:doctor_app_flutter/config/size_config.dart';
import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart';
import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
-import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
-import 'package:doctor_app_flutter/widgets/dashboard/guage_chart.dart';
import 'package:doctor_app_flutter/widgets/dashboard/out_patient_stack.dart';
-import 'package:doctor_app_flutter/widgets/dashboard/row_count.dart';
import 'package:doctor_app_flutter/widgets/dashboard/swiper_rounded_pagination.dart';
-import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
import 'package:doctor_app_flutter/widgets/shared/rounded_container_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
-import 'package:charts_flutter/flutter.dart' as charts;
+
+import 'dashboard_referral_patient.dart';
class DashboardSwipeWidget extends StatefulWidget {
final List dashboardItemList;
@@ -28,8 +25,10 @@ class _DashboardSwipeWidgetState extends State {
@override
Widget build(BuildContext context) {
+ double height = SizeConfig.heightMultiplier *
+ (SizeConfig.isHeightVeryShort ? 40 : SizeConfig.isHeightLarge?33:31);
return Container(
- height: MediaQuery.of(context).size.height * 0.35,
+ height: height,
// height: 230,
child: Swiper(
onIndexChanged: (index) {
@@ -41,10 +40,10 @@ class _DashboardSwipeWidgetState extends State {
}
},
itemBuilder: (BuildContext context, int index) {
- return getSwipeWidget(widget.dashboardItemList, index);
+ return getSwipeWidget(widget.dashboardItemList, index, height);
},
itemCount: 3,
- // itemHeight: 300,
+
pagination: new SwiperCustomPagination(builder: (BuildContext context, SwiperPluginConfig config) {
return new Stack(
alignment: Alignment.bottomCenter,
@@ -77,21 +76,24 @@ class _DashboardSwipeWidgetState extends State {
);
}
- Widget getSwipeWidget(List dashboardItemList, int index) {
+ Widget getSwipeWidget(List dashboardItemList, int index, double height) {
if (index == 1)
return RoundedContainer(
- raduis: 16,
- showBorder: true,
+ raduis: 16,
+ showBorder: false,
borderColor: Colors.white,
shadowWidth: 0.2,
shadowSpreadRadius: 3,
shadowDy: 1,
margin: EdgeInsets.only(top: 15, bottom: 15, left: 10, right: 10),
- child: Padding(padding: const EdgeInsets.all(5.0), child: GetOutPatientStack(dashboardItemList[1])));
+ child: Padding(padding: const EdgeInsets.all(5.0), child: GetOutPatientStack(dashboardItemList[1],
+ ),
+ ),
+ );
if (index == 0)
return RoundedContainer(
raduis: 16,
- showBorder: true,
+ showBorder: false,
borderColor: Colors.white,
shadowWidth: 0.2,
shadowSpreadRadius: 3,
@@ -99,118 +101,12 @@ class _DashboardSwipeWidgetState extends State {
margin: EdgeInsets.only(top: 15, bottom: 15, left: 10, right: 10),
child: Padding(padding: const EdgeInsets.all(5.0), child: GetOutPatientStack(dashboardItemList[0])));
if (index == 2)
- return RoundedContainer(
- raduis: 16,
- showBorder: true,
- borderColor: Colors.white,
- shadowWidth: 0.2,
- shadowSpreadRadius: 3,
- shadowDy: 1,
- margin: EdgeInsets.only(top: 15, bottom: 15, left: 10, right: 10),
- child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
- Expanded(
- flex: 1,
- child: Row(
- children: [
- Expanded(
- flex: 4,
- child: Padding(
- padding: const EdgeInsets.all(5.0),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Padding(
- padding: EdgeInsets.all(8),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AppText(
- TranslationBase.of(context).patients,
- fontSize: 12,
- fontWeight: FontWeight.bold,
- fontHeight: 0.5,
- ),
- AppText(
- TranslationBase.of(context).referral,
- fontSize: 22,
- fontWeight: FontWeight.bold,
- ),
- ],
- )),
- Expanded(
- flex: 1,
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Expanded(
- child: RowCounts(dashboardItemList[2].summaryoptions![0].kPIParameter,
- dashboardItemList[2].summaryoptions![0].value!, Colors.black),
- ),
- Expanded(
- child: RowCounts(dashboardItemList[2].summaryoptions![1].kPIParameter,
- dashboardItemList[2].summaryoptions![1].value!, Colors.grey),
- ),
- Expanded(
- child: RowCounts(dashboardItemList[2].summaryoptions![2].kPIParameter,
- dashboardItemList[2].summaryoptions![2].value!, Colors.red),
- ),
- ],
- ),
- )
- ],
- )),
- ),
- Expanded(
- flex: 3,
- child: Stack(children: [
- Container(child: GaugeChart(_createReferralData(widget.dashboardItemList))),
- Positioned(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.center,
- children: [
- AppText(
- widget.model.getPatientCount(dashboardItemList[2]).toString(),
- fontSize: SizeConfig.textMultiplier * 3.0,
- fontWeight: FontWeight.bold,
- )
- ],
- ),
- top: MediaQuery.of(context).size.height * 0.13,
- left: 0,
- right: 0)
- ]),
- ),
- ],
- )),
- ]));
+ return DashboardReferralPatient(dashboardItemList: widget.dashboardItemList,height: height,model: widget.model,);
return Container();
}
- static List> _createReferralData(List dashboardItemList) {
- final data = [
- new GaugeSegment(dashboardItemList[2].summaryoptions![0].kPIParameter!,
- getValue(dashboardItemList[1].summaryoptions![0].value), charts.MaterialPalette.black),
- new GaugeSegment(dashboardItemList[2].summaryoptions![1].kPIParameter!,
- getValue(dashboardItemList[1].summaryoptions![1].value), charts.MaterialPalette.gray.shadeDefault),
- new GaugeSegment(dashboardItemList[2].summaryoptions![2].kPIParameter!,
- getValue(dashboardItemList[1].summaryoptions![2].value), charts.MaterialPalette.red.shadeDefault),
- ];
- return [
- new charts.Series(
- id: 'Segments',
- domainFn: (GaugeSegment segment, _) => segment.segment,
- measureFn: (GaugeSegment segment, _) => segment.size,
- data: data,
- colorFn: (GaugeSegment segment, _) => segment.color,
- )
- ];
- }
- static int getValue(value) {
- return value == 0 ? 1 : value;
- }
}
+
+
diff --git a/lib/screens/home/home_page_card.dart b/lib/screens/home/home_page_card.dart
index c4743f3b..2dac78b9 100644
--- a/lib/screens/home/home_page_card.dart
+++ b/lib/screens/home/home_page_card.dart
@@ -10,7 +10,7 @@ class HomePageCard extends StatelessWidget {
Key? key,
required this.color,
this.opacity = 0.4,
- required this.margin})
+ required this.margin, this.width})
: super(key: key);
final bool hasBorder;
final String? imageName;
@@ -18,16 +18,16 @@ class HomePageCard extends StatelessWidget {
final GestureTapCallback onTap;
final Color color;
final double opacity;
+ final double width;
final EdgeInsets margin;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Container(
- width: 120,
- height: MediaQuery.of(context).orientation == Orientation.portrait ? 100 : 200,
+ width: width,
margin: this.margin,
- decoration: BoxDecoration(
+ decoration: BoxDecoration(
color: !hasBorder
? color != null
? color
diff --git a/lib/screens/home/home_patient_card.dart b/lib/screens/home/home_patient_card.dart
index f0bee0cb..798b73cd 100644
--- a/lib/screens/home/home_patient_card.dart
+++ b/lib/screens/home/home_patient_card.dart
@@ -10,6 +10,7 @@ class HomePatientCard extends StatelessWidget {
final String text;
final Color textColor;
final GestureTapCallback onTap;
+ final double iconSize;
HomePatientCard({
required this.backgroundColor,
@@ -18,13 +19,17 @@ class HomePatientCard extends StatelessWidget {
required this.text,
required this.textColor,
required this.onTap,
+ this.iconSize = 30,
});
@override
Widget build(BuildContext context) {
+ double width = SizeConfig.heightMultiplier*
+ (SizeConfig.isHeightVeryShort ? 16 : SizeConfig.isHeightLarge?15:13);
return HomePageCard(
color: backgroundColor,
- margin: EdgeInsets.all(4),
+ width: width,
+ margin: EdgeInsets.all(SizeConfig.widthMultiplier *1.121),
child: Container(
padding: EdgeInsets.all(8),
child: Column(
@@ -35,13 +40,14 @@ class HomePatientCard extends StatelessWidget {
child: Stack(
children: [
Positioned(
- bottom: 0.1,
- right: 0.5,
- width: 23.0,
- height: 25.0,
+ top: SizeConfig.isHeightVeryShort ? 8 : 8,
+ left: SizeConfig.isHeightVeryShort ? 5 : 10,
+ width: SizeConfig.getWidthMultiplier(width: width) * 10,
+ height: SizeConfig.getWidthMultiplier(width: width) * 15,
child: Icon(
cardIcon,
- size: 60,
+ size: SizeConfig.getWidthMultiplier(width: width) *
+ (SizeConfig.isHeightVeryShort ? 45 : 60),
color: backgroundIconColor,
),
),
@@ -52,7 +58,8 @@ class HomePatientCard extends StatelessWidget {
children: [
Icon(
cardIcon,
- size: 30,
+ size:
+ SizeConfig.getWidthMultiplier(width: width) * 22,
color: textColor,
),
SizedBox(
@@ -70,7 +77,9 @@ class HomePatientCard extends StatelessWidget {
text,
color: textColor,
textAlign: TextAlign.start,
- fontSize: SizeConfig.textMultiplier * 1.6,
+ fontSize:
+ SizeConfig.getTextMultiplierBasedOnWidth(width: width) *
+ (SizeConfig.isHeightVeryShort ? 11 : 10),
),
),
),
diff --git a/lib/screens/home/home_screen.dart b/lib/screens/home/home_screen.dart
index e5c08cbc..d0fb3569 100644
--- a/lib/screens/home/home_screen.dart
+++ b/lib/screens/home/home_screen.dart
@@ -1,14 +1,10 @@
-import 'package:doctor_app_flutter/config/config.dart';
-import 'package:doctor_app_flutter/core/enum/viewstate.dart';
+import 'package:doctor_app_flutter/config/size_config.dart';
import 'package:doctor_app_flutter/core/model/patient_muse/PatientSearchRequestModel.dart';
import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/dashboard_view_model.dart';
import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart';
import 'package:doctor_app_flutter/icons_app/doctor_app_icons.dart';
-import 'package:doctor_app_flutter/models/dashboard/dashboard_model.dart';
-import 'package:doctor_app_flutter/models/doctor/clinic_model.dart';
import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart';
-import 'package:doctor_app_flutter/models/patient/patient_model.dart';
import 'package:doctor_app_flutter/screens/base/base_view.dart';
import 'package:doctor_app_flutter/screens/home/dashboard_slider-item-widget.dart';
import 'package:doctor_app_flutter/screens/home/dashboard_swipe_widget.dart';
@@ -20,20 +16,15 @@ import 'package:doctor_app_flutter/screens/patients/out_patient/out_patient_scre
import 'package:doctor_app_flutter/screens/patients/patient_search/patient_search_screen.dart';
import 'package:doctor_app_flutter/screens/patients/profile/referral/patient_referral_screen.dart';
import 'package:doctor_app_flutter/util/date-utils.dart';
-import 'package:doctor_app_flutter/util/dr_app_toast_msg.dart';
-import 'package:doctor_app_flutter/util/helpers.dart';
import 'package:doctor_app_flutter/util/translations_delegate_base.dart';
-import 'package:doctor_app_flutter/widgets/patients/profile/profile-welcome-widget.dart';
import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart';
-import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
-import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart';
import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
-import 'package:sticky_headers/sticky_headers/widget.dart';
-import '../../widgets/shared/app_texts_widget.dart';
+import 'home_screen_header.dart';
+import 'label.dart';
class HomeScreen extends StatefulWidget {
HomeScreen({Key? key, this.title}) : super(key: key);
@@ -47,15 +38,16 @@ class HomeScreen extends StatefulWidget {
class _HomeScreenState extends State {
bool isLoading = false;
- late ProjectViewModel projectsProvider;
- var _isInit = true;
- late DoctorProfileModel profile;
+ ProjectViewModel projectsProvider;
+ DoctorProfileModel profile;
bool isExpanded = false;
bool isInpatient = false;
int sliderActiveIndex = 0;
- var clinicId;
+ String clinicId;
late AuthenticationViewModel authenticationViewModel;
int colorIndex = 0;
+ final GlobalKey scaffoldKey = new GlobalKey();
+
@override
Widget build(BuildContext context) {
@@ -68,222 +60,137 @@ class _HomeScreenState extends State {
}
return BaseView(
+
onModelReady: (model) async {
await model.setFirebaseNotification(projectsProvider, authenticationViewModel);
await model.getDashboard();
await model.getDoctorProfile(isGetProfile: true);
await model.checkDoctorHasLiveCare();
+ // await model.getSpecialClinicalCareList();
},
builder: (_, model, w) => AppScaffold(
baseViewModel: model,
- isShowAppBar: false,
+ isShowAppBar: true,
+ appBar: HomeScreenHeader(
+ model: model,
+ onOpenDrawer: (){
+ Scaffold.of(context).openDrawer();
+ },
+ ),
body: ListView(children: [
Column(children: [
- StickyHeader(
- header: Container(
- color: Colors.grey[100],
- padding: EdgeInsets.only(top: 10),
- child: Stack(children: [
- IconButton(
- icon: Image.asset('assets/images/menu.png', height: 50, width: 50),
- iconSize: 18,
- color: Colors.black,
- onPressed: () => Scaffold.of(context).openDrawer(),
- ),
- Column(children: [
- ProfileWelcomeWidget(
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Container(
- width: MediaQuery.of(context).size.width * .6,
- child: projectsProvider.doctorClinicsList.length > 0
- ? Stack(
- children: [
- DropdownButtonHideUnderline(
- child: DropdownButton(
- dropdownColor: Colors.white,
- iconEnabledColor: Colors.black,
- isExpanded: true,
- value: clinicId == null
- ? projectsProvider.doctorClinicsList[0].clinicID
- : clinicId,
- iconSize: 25,
- elevation: 16,
- selectedItemBuilder: (BuildContext context) {
- return projectsProvider.doctorClinicsList.map((item) {
- return Row(
- mainAxisSize: MainAxisSize.max,
- mainAxisAlignment: MainAxisAlignment.end,
- children: [
- Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- Container(
- padding: EdgeInsets.all(2),
- margin: EdgeInsets.all(2),
- decoration: new BoxDecoration(
- color: Colors.red[800],
- borderRadius: BorderRadius.circular(20),
- ),
- constraints: BoxConstraints(
- minWidth: 20,
- minHeight: 20,
- ),
- child: Center(
- child: AppText(
- projectsProvider.doctorClinicsList.length.toString(),
- color: Colors.white,
- fontSize: projectsProvider.isArabic ? 10 : 11,
- textAlign: TextAlign.center,
- ),
- )),
- ],
- ),
- AppText(item.clinicName,
- fontSize: 12,
- color: Colors.black,
- fontWeight: FontWeight.bold,
- textAlign: TextAlign.end),
- ],
- );
- }).toList();
- },
- onChanged: (newValue) async {
- clinicId = newValue;
- GifLoaderDialogUtils.showMyDialog(context);
- await model.changeClinic(clinicId, authenticationViewModel);
- GifLoaderDialogUtils.hideDialog(context);
- if (model.state == ViewState.ErrorLocal) {
- DrAppToastMsg.showErrorToast(model.error);
- }
- },
- items: projectsProvider.doctorClinicsList.map((item) {
- return DropdownMenuItem(
- child: AppText(
- item.clinicName,
- textAlign: TextAlign.left,
- ),
- value: item.clinicID,
- );
- }).toList(),
- )),
- ],
- )
- : AppText(TranslationBase.of(context).noClinic),
- ),
- ],
- ),
- isClinic: true,
- height: 50,
- ),
- ])
- ])),
- content: Column(
- children: [
- model.dashboardItemsList.length > 0
- ? DashboardSwipeWidget(
- model.dashboardItemsList,
- model,
- (sliderIndex) {
- setState(() {
- sliderActiveIndex = sliderIndex;
- });
- },
- )
- : SizedBox(),
- model.dashboardItemsList.length > 0
- ? FractionallySizedBox(
- widthFactor: 0.90,
- child: Container(
- child: Column(mainAxisAlignment: MainAxisAlignment.start, children: [
- SizedBox(
- height: 10,
- ),
- sliderActiveIndex == 1
- ? DashboardSliderItemWidget(model.dashboardItemsList[4])
- : sliderActiveIndex == 0
- ? DashboardSliderItemWidget(model.dashboardItemsList[3])
- : DashboardSliderItemWidget(model.dashboardItemsList[6]),
- ])))
- : SizedBox(),
- FractionallySizedBox(
- // widthFactor: 0.90,
+ // SizedBox(
+ // height: SizeConfig.heightMultiplier * 1.4,
+ // ),
+ model.dashboardItemsList.length > 0
+ ? DashboardSwipeWidget(
+ model.dashboardItemsList,
+ model,
+ (sliderIndex) {
+ setState(() {
+ sliderActiveIndex = sliderIndex;
+ });
+ },
+ )
+ : SizedBox(),
+
+ // SizedBox(
+ // height: SizeConfig.heightMultiplier * 1.4,
+ // ),
+ model.dashboardItemsList.length > 0
+ ? FractionallySizedBox(
+ widthFactor: 0.94,
child: Container(
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.only(
- topRight: Radius.circular(50),
- )),
- padding: EdgeInsets.only(left: 20, top: 10, right: 20),
- margin: EdgeInsets.only(top: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.start,
children: