video stream add record icon and change button disable

merge-requests/755/head
mosazaid 3 years ago
parent db4501bd14
commit 385820fdce

@ -54,8 +54,9 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
val generalId = call.argument<String>("generalId")
val doctorId = call.argument<Int>("DoctorId")
val patientName = call.argument<String>("patientName")
val isRecording = call.argument<Boolean>("isRecording")
val sessionStatusModel = GetSessionStatusModel(VC_ID, tokenID, generalId, doctorId, patientName)
val sessionStatusModel = GetSessionStatusModel(VC_ID, tokenID, generalId, doctorId, patientName, isRecording!!)
openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel)

@ -23,16 +23,20 @@ public class GetSessionStatusModel implements Parcelable {
@SerializedName("PatientName")
@Expose
private String patientName;
@SerializedName("isRecording")
@Expose
private boolean isRecording;
public GetSessionStatusModel() {
}
public GetSessionStatusModel(Integer vCID, String tokenID, String generalid, Integer doctorId, String patientName) {
public GetSessionStatusModel(Integer vCID, String tokenID, String generalid, Integer doctorId, String patientName, boolean isRecording) {
this.vCID = vCID;
this.tokenID = tokenID;
this.generalid = generalid;
this.doctorId = doctorId;
this.patientName = patientName;
this.isRecording = isRecording;
}
protected GetSessionStatusModel(Parcel in) {
@ -49,6 +53,7 @@ public class GetSessionStatusModel implements Parcelable {
doctorId = in.readInt();
}
patientName = in.readString();
isRecording = in.readInt() == 1;
}
public static final Creator<GetSessionStatusModel> CREATOR = new Creator<GetSessionStatusModel>() {
@ -105,6 +110,14 @@ public class GetSessionStatusModel implements Parcelable {
this.patientName = patientName;
}
public boolean isRecording() {
return isRecording;
}
public void setRecording(boolean recording) {
isRecording = recording;
}
@Override
public int describeContents() {
return 0;
@ -127,5 +140,6 @@ public class GetSessionStatusModel implements Parcelable {
dest.writeInt(doctorId);
}
dest.writeString(patientName);
dest.writeInt(isRecording ? 1 : 0);
}
}

@ -38,8 +38,9 @@ import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks
import kotlin.math.ceil
class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.SessionListener, PublisherListener,
SubscriberKit.VideoListener, VideoCallView {
class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.SessionListener,
PublisherListener,
SubscriberKit.VideoListener, VideoCallView {
private var isFullScreen: Boolean = true
private var isCircle: Boolean = false
@ -62,6 +63,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private var mVolRunnable: Runnable? = null
private var mConnectedRunnable: Runnable? = null
private lateinit var recordContainer: FrameLayout
private lateinit var thumbnail_container: FrameLayout
private lateinit var mPublisherViewContainer: FrameLayout
private lateinit var mPublisherViewIcon: View
@ -74,6 +76,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private var token: String? = null
private var appLang: String? = null
private var baseUrl: String? = null
private var isRecording: Boolean = true
private var isSwitchCameraClicked = false
private var isCameraClicked = false
@ -117,8 +120,8 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
super.onStart()
dialog?.window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
}
@ -156,8 +159,8 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
// Make the dialog possible to be outside touch
dialogWindow!!.setFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
)
dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
requireView().invalidate()
@ -168,8 +171,10 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
this.videoCallResponseListener = videoCallResponseListener
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
parentView = inflater.inflate(R.layout.activity_video_call, container, false)
@ -181,12 +186,17 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
appLang = getString("appLang")
baseUrl = getString("baseUrl")
sessionStatusModel = getParcelable("sessionStatusModel")
if (sessionStatusModel != null)
isRecording = sessionStatusModel!!.isRecording
}
initUI(parentView)
requestPermissions()
handleDragDialog()
mDetector = GestureDetectorCompat(context, MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }))
mDetector = GestureDetectorCompat(
context,
MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() })
)
return parentView
}
@ -223,6 +233,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
layoutName = view.findViewById(R.id.layout_name)
layoutMini = view.findViewById(R.id.layout_mini)
icMini = view.findViewById(R.id.ic_mini)
recordContainer = view.findViewById(R.id.record_container)
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)
@ -232,23 +243,30 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
patientName = view.findViewById<TextView>(R.id.patient_name)
patientName.text = sessionStatusModel!!.patientName
if (isRecording) {
recordContainer.visibility = View.VISIBLE
} else {
recordContainer.visibility = View.GONE
}
cmTimer = view.findViewById<Chronometer>(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
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")
}
arg0?.text = "$minutes:$seconds"
Log.d(VideoCallFragment.TAG, "onChronometerTick: $minutes : $seconds")
}
icMini.setOnClickListener {
onMiniCircleClicked()
@ -310,7 +328,11 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong())
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>, grantResults: IntArray) {
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}
@ -323,19 +345,25 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
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()
.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)
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()
@ -345,7 +373,12 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
e.printStackTrace()
}
} else {
EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, *perms)
EasyPermissions.requestPermissions(
this,
getString(R.string.remaining_ar),
RC_VIDEO_APP_PERM,
*perms
)
}
}
@ -354,7 +387,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
mPublisher = Publisher.Builder(requireContext())
// .name("publisher")
// .renderer(ThumbnailCircleVideoRenderer(requireContext()))
.build()
.build()
mPublisher!!.setPublisherListener(this)
if (mPublisher!!.view is GLSurfaceView) {
(mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true)
@ -387,7 +420,10 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
}
override fun onStreamReceived(session: Session, stream: Stream) {
Log.d(TAG, "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId)
Log.d(
TAG,
"onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId
)
if (mSubscriber != null) {
isConnected = true
return
@ -396,11 +432,22 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
subscribeToStream(stream)
if (mConnectedHandler != null && mConnectedRunnable != null)
mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!)
videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(3, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
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)
Log.d(
TAG,
"onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId
)
if (mSubscriber == null) {
return
}
@ -427,7 +474,10 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
}
override fun onVideoDataReceived(subscriberKit: SubscriberKit?) {
mSubscriber!!.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
mSubscriber!!.setStyle(
BaseVideoRenderer.STYLE_VIDEO_SCALE,
BaseVideoRenderer.STYLE_VIDEO_FILL
)
(mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false)
mSubscriberViewContainer.addView(mSubscriber!!.view)
// switchToThumbnailCircle()
@ -477,8 +527,8 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private fun subscribeToStream(stream: Stream) {
mSubscriber = Subscriber.Builder(requireContext(), stream)
.renderer(DynamicVideoRenderer(requireContext()))
.build()
.renderer(DynamicVideoRenderer(requireContext()))
.build()
mSubscriber!!.setVideoListener(this)
mSession!!.subscribe(mSubscriber)
}
@ -506,7 +556,15 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
mSession!!.disconnect()
countDownTimer?.cancel()
videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(16, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
videoCallPresenter.callChangeCallStatus(
ChangeCallStatusRequestModel(
16,
sessionStatusModel!!.doctorId,
sessionStatusModel!!.generalid,
token,
sessionStatusModel!!.vcid
)
)
dialog?.dismiss()
}
@ -546,13 +604,13 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private fun onMiniCircleClicked() {
if (isCircle) {
dialog?.window?.setLayout(
400,
600
400,
600
)
} else {
dialog?.window?.setLayout(
300,
300
300,
300
)
}
isCircle = !isCircle
@ -561,11 +619,23 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
(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)
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.remoteBackground))
videoCallContainer.setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.text_color
)
)
mSubscriberViewContainer.setBackgroundColor(
ContextCompat.getColor(
requireContext(),
R.color.remoteBackground
)
)
}
}
@ -582,13 +652,13 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private fun onMinimizedClicked(view: View?) {
if (isFullScreen) {
dialog?.window?.setLayout(
400,
600
400,
600
)
} else {
dialog?.window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
}
isFullScreen = !isFullScreen
@ -602,24 +672,34 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
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 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 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
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
@ -638,7 +718,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
localPreviewLayoutParam.width = localPreviewWidth
localPreviewLayoutParam.height = localPreviewHeight
localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0)
if (mPublisher != null && mPublisher!!.view.parent == null){
if (mPublisher != null && mPublisher!!.view.parent == null) {
mPublisherViewContainer.addView(mPublisher!!.view)
}
mPublisherViewContainer.visibility = View.VISIBLE
@ -666,7 +746,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
localPreviewLayoutParam.height = 0
localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0)
if (mPublisher != null){
if (mPublisher != null) {
mPublisherViewContainer.removeView(mPublisher!!.view)
}
mPublisherViewContainer.visibility = View.GONE
@ -814,7 +894,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes
mParams.x =
(szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt()
(szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt()
dialog!!.window!!.attributes = mParams
val x = szWindow.x - current_x_cord
@ -825,7 +905,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
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()
(szWindow.x - current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
dialog!!.window!!.attributes = mParams
}
@ -851,7 +931,7 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
override fun onTick(t: Long) {
val step = (500 - t) / 5
mParams.x =
(szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
(szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
dialog!!.window!!.attributes = mParams
}
@ -866,17 +946,20 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private fun getWindowManagerDefaultDisplay() {
mWindowManager.getDefaultDisplay()
.getSize(szWindow)
.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()
(25 * requireActivity().applicationContext.resources.displayMetrics.density).toDouble()
).toInt()
}
private class MyGestureListener(val onTabCall: () -> Unit, val miniCircleDoubleTap: () -> Unit) : GestureDetector.SimpleOnGestureListener() {
private class MyGestureListener(
val onTabCall: () -> Unit,
val miniCircleDoubleTap: () -> Unit
) : GestureDetector.SimpleOnGestureListener() {
override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
// onTabCall()
@ -893,9 +976,9 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
companion object {
@JvmStatic
fun newInstance(args: Bundle) =
VideoCallFragment().apply {
arguments = args
}
VideoCallFragment().apply {
arguments = args
}
private val TAG = VideoCallFragment::class.java.simpleName

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM13.05,9.79L10,7.5v9l3.05,-2.29L16,12zM11,4.07L11,2.05c-2.01,0.2 -3.84,1 -5.32,2.21L7.1,5.69c1.11,-0.86 2.44,-1.44 3.9,-1.62zM5.69,7.1L4.26,5.68C3.05,7.16 2.25,8.99 2.05,11h2.02c0.18,-1.46 0.76,-2.79 1.62,-3.9zM4.07,13L2.05,13c0.2,2.01 1,3.84 2.21,5.32l1.43,-1.43c-0.86,-1.1 -1.44,-2.43 -1.62,-3.89zM5.68,19.74C7.16,20.95 9,21.75 11,21.95v-2.02c-1.46,-0.18 -2.79,-0.76 -3.9,-1.62l-1.42,1.43zM22,12c0,5.16 -3.92,9.42 -8.95,9.95v-2.02C16.97,19.41 20,16.05 20,12s-3.03,-7.41 -6.95,-7.93L13.05,2.05C18.08,2.58 22,6.84 22,12z"/>
</vector>

@ -108,6 +108,23 @@
android:src="@drawable/video_off_fill" />
</FrameLayout>
<FrameLayout
android:id="@+id/record_container"
android:layout_width="@dimen/local_preview_width"
android:layout_height="@dimen/local_preview_height"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:visibility="visible">
<ImageView
android:id="@+id/record_icon"
android:layout_width="@dimen/local_back_icon_size"
android:layout_height="@dimen/local_back_icon_size"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@drawable/ic_record" />
</FrameLayout>
<FrameLayout
android:id="@+id/thumbnail_container"
android:layout_width="90dp"

@ -16,62 +16,82 @@ import '../../locator.dart';
import '../../routes.dart';
import 'NavigationService.dart';
class VideoCallService extends BaseService{
class VideoCallService extends BaseService {
StartCallRes startCallRes;
PatiantInformtion patient;
LiveCarePatientServices _liveCarePatientServices = locator<LiveCarePatientServices>();
LiveCarePatientServices _liveCarePatientServices =
locator<LiveCarePatientServices>();
openVideo(StartCallRes startModel,PatiantInformtion patientModel,VoidCallback onCallConnected, VoidCallback onCallDisconnected)async{
openVideo(
StartCallRes startModel,
PatiantInformtion patientModel,
bool isRecording,
VoidCallback onCallConnected,
VoidCallback onCallDisconnected) async {
this.startCallRes = startModel;
this.patient = patientModel;
DoctorProfileModel doctorProfile = await getDoctorProfile(isGetProfile: true);
DoctorProfileModel doctorProfile =
await getDoctorProfile(isGetProfile: true);
await VideoChannel.openVideoCallScreen(
kToken: startCallRes.openTokenID,
kSessionId:startCallRes.openSessionID,
kApiKey: '46209962' ,//'46209962'
kToken: startCallRes.openTokenID,
kSessionId: startCallRes.openSessionID,
kApiKey: '46209962',
vcId: patient.vcId,
patientName: patient.fullName ?? (patient.firstName != null ? "${patient.firstName} ${patient.lastName}" : "-"),
isRecording: isRecording,
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,
},
onCallConnected: onCallConnected,
onCallEnd: () {
WidgetsBinding.instance.addPostFrameCallback((_) async {
GifLoaderDialogUtils.showMyDialog(locator<NavigationService>().navigatorKey.currentContext);
endCall(patient.vcId, false,).then((value) {
GifLoaderDialogUtils.hideDialog(locator<NavigationService>().navigatorKey.currentContext);
if (hasError) {
DrAppToastMsg.showErrorToast(error);
}else
locator<NavigationService>().navigateTo(PATIENTS_END_Call,arguments: {
"patient": patient,
});
});
GifLoaderDialogUtils.showMyDialog(
locator<NavigationService>().navigatorKey.currentContext);
endCall(
patient.vcId,
false,
).then((value) {
GifLoaderDialogUtils.hideDialog(
locator<NavigationService>().navigatorKey.currentContext);
if (hasError) {
DrAppToastMsg.showErrorToast(error);
} else
locator<NavigationService>()
.navigateTo(PATIENTS_END_Call, arguments: {
"patient": patient,
});
});
});
},
onCallNotRespond: (SessionStatusModel sessionStatusModel) {
WidgetsBinding.instance.addPostFrameCallback((_) {
GifLoaderDialogUtils.showMyDialog(locator<NavigationService>().navigatorKey.currentContext);
endCall(patient.vcId, sessionStatusModel.sessionStatus == 3,).then((value) {
GifLoaderDialogUtils.hideDialog(locator<NavigationService>().navigatorKey.currentContext);
GifLoaderDialogUtils.showMyDialog(
locator<NavigationService>().navigatorKey.currentContext);
endCall(
patient.vcId,
sessionStatusModel.sessionStatus == 3,
).then((value) {
GifLoaderDialogUtils.hideDialog(
locator<NavigationService>().navigatorKey.currentContext);
if (hasError) {
DrAppToastMsg.showErrorToast(error);
} else {
locator<NavigationService>().navigateTo(PATIENTS_END_Call,arguments: {
locator<NavigationService>()
.navigateTo(PATIENTS_END_Call, arguments: {
"patient": patient,
});
}
});
});
});
});
}
Future endCall(int vCID, bool isPatient) async {
hasError = false;
await getDoctorProfile(isGetProfile: true);
@ -85,5 +105,4 @@ class VideoCallService extends BaseService{
error = _liveCarePatientServices.error;
}
}
}
}

@ -5,6 +5,7 @@ class StartCallRes {
bool isAuthenticated;
int messageStatus;
String appointmentNo;
bool isRecording;
StartCallRes(
{this.result,
@ -12,7 +13,9 @@ class StartCallRes {
this.openTokenID,
this.isAuthenticated,
this.appointmentNo,
this.messageStatus});
this.messageStatus,
this.isRecording = true,
});
StartCallRes.fromJson(Map<String, dynamic> json) {
result = json['Result'];
@ -21,6 +24,7 @@ class StartCallRes {
isAuthenticated = json['IsAuthenticated'];
messageStatus = json['MessageStatus'];
appointmentNo = json['AppointmentNo'];
isRecording = json['isRecording'];
}
Map<String, dynamic> toJson() {
@ -31,6 +35,7 @@ class StartCallRes {
data['IsAuthenticated'] = this.isAuthenticated;
data['MessageStatus'] = this.messageStatus;
data['AppointmentNo'] = this.appointmentNo;
data['isRecording'] = this.isRecording;
return data;
}
}

@ -79,6 +79,7 @@ class _EndCallScreenState extends State<EndCallScreen> {
kSessionId: liveCareModel.startCallRes.openSessionID,
kApiKey: '46209962',
vcId: patient.vcId,
isRecording: liveCareModel.startCallRes != null ? liveCareModel.startCallRes.isRecording: false,
patientName: patient.fullName ?? (patient.firstName != null ? "${patient.firstName} ${patient.lastName}" : "-"),
tokenID: await liveCareModel.getToken(),
generalId: GENERAL_ID,

@ -66,6 +66,7 @@ class _VideoCallPageState extends State<VideoCallPage> {
//'1_MX40NjgwMzIyNH5-MTU5MzY4MzYzODYwM35ucExWYVRVSm5Hcy9uWGZmM1lOa3czZHV-fg',
kApiKey: '46209962',
vcId: widget.patientData.vcId,
isRecording: tokenData != null ? tokenData.isRecording: false,
patientName: widget.patientData.fullName ?? widget.patientData.firstName != null ? "${widget.patientData.firstName} ${widget.patientData.lastName}" : "-",
tokenID: token, //"hfkjshdf347r8743",
generalId: "Cs2020@2016\$2958",

@ -57,6 +57,7 @@ class _PatientProfileScreenState extends State<PatientProfileScreen>
StreamController<String> videoCallDurationStreamController;
Stream<String> videoCallDurationStream = (() async*{})();
@override
void initState() {
_tabController = TabController(length: 2, vsync: this);
@ -119,6 +120,10 @@ class _PatientProfileScreenState extends State<PatientProfileScreen>
callDisconnected(){
callTimer.cancel();
videoCallDurationStreamController.sink.add(null);
setState(() {
isCallStarted = false;
});
}
@override
@ -350,7 +355,7 @@ class _PatientProfileScreenState extends State<PatientProfileScreen>
});
GifLoaderDialogUtils.hideDialog(context);
AppPermissionsUtils.requestVideoCallPermission(context: context,onTapGrant: (){
locator<VideoCallService>().openVideo(model.startCallRes, patient, callConnected, callDisconnected);
locator<VideoCallService>().openVideo(model.startCallRes, patient, model.startCallRes.isRecording, callConnected, callDisconnected);
});
}
}

@ -11,7 +11,7 @@ class VideoChannel{
/// channel name
static const _channel = const MethodChannel("Dr.cloudSolution/videoCall");
static openVideoCallScreen({kApiKey, kSessionId, kToken, callDuration, warningDuration,int vcId,String tokenID,
String generalId,int doctorId, String patientName, Function() onCallEnd ,
String generalId,int doctorId, String patientName, bool isRecording = false, Function() onCallEnd ,
Function(SessionStatusModel sessionStatusModel) onCallNotRespond ,Function(String error) onFailure, VoidCallback onCallConnected, VoidCallback onCallDisconnected}) async {
onCallConnected = onCallConnected ?? (){};
@ -41,6 +41,7 @@ class VideoChannel{
"generalId": generalId,
"DoctorId": doctorId ,
"patientName": patientName,
"isRecording": isRecording,
},
);
if(result['callResponse'] == 'CallEnd') {

Loading…
Cancel
Save