diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d290213..bf8d4218 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -7,6 +7,15 @@ # The following line activates a set of recommended lints for Flutter apps, # packages, and plugins designed to encourage good coding practices. +analyzer: + exclude: + - build/** + - android/** + - ios/** + - web/** + - windows/** + - macos/** + - linux/** include: package:flutter_lints/flutter.yaml linter: diff --git a/android/app/build.gradle b/android/app/build.gradle index 745172a3..f52eb79a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -30,7 +30,7 @@ if (flutterVersionName == null) { android { namespace "com.hmg.hmgDr" - compileSdkVersion 35 + compileSdkVersion 37 signingConfigs { release { @@ -52,8 +52,8 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.hmg.hmgDr" - minSdkVersion 24 - targetSdkVersion 35 + minSdkVersion 28 + targetSdkVersion 37 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -67,7 +67,7 @@ android { debuggable false minifyEnabled true shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles 'proguard-rules.pro' } debug { @@ -129,7 +129,7 @@ dependencies { //openTok - implementation 'com.opentok.android:opentok-android-sdk:2.20.1' + implementation 'com.opentok.android:opentok-android-sdk:2.35.1' //permissions // implementation 'pub.devrel:easypermissions:0.4.0' // implementation project(':easypermissions') diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt index 7f9d2a42..ffd72c4b 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt @@ -16,7 +16,7 @@ import android.util.Log import android.widget.Toast import androidx.annotation.NonNull import com.google.gson.GsonBuilder -import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService +//import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService import com.hmg.hmgDr.Model.GetSessionStatusModel import com.hmg.hmgDr.Model.SessionStatusModel import com.hmg.hmgDr.ui.VideoCallResponseListener @@ -43,7 +43,7 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, private val LAUNCH_VIDEO: Int = 1 private var serviceIntent: Intent? = null - private var videoStreamService: VideoStreamFloatingWidgetService? = null +// private var videoStreamService: VideoStreamFloatingWidgetService? = null private var bound = false override fun onCreate(savedInstanceState: Bundle?) { @@ -59,46 +59,46 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - this.result = result - this.call = call - - 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") - val isRecording = call.argument("isRecording") - - val sessionStatusModel = - GetSessionStatusModel( - VC_ID, - tokenID, - generalId, - doctorId, - patientName, - isRecording!! - ) - - - openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel) - - } - "closeVideoCall" -> { - videoStreamService?.closeVideoCall() - } - else -> { - result.notImplemented() - } - } +// this.result = result +// this.call = call +// +// 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") +// val isRecording = call.argument("isRecording") +// +// val sessionStatusModel = +// GetSessionStatusModel( +// VC_ID, +// tokenID, +// generalId, +// doctorId, +// patientName, +// isRecording!! +// ) +// +// +// openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel) +// +// } +// "closeVideoCall" -> { +// videoStreamService?.closeVideoCall() +// } +// else -> { +// result.notImplemented() +// } +// } } private fun openVideoCall( @@ -110,24 +110,24 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, sessionStatusModel: GetSessionStatusModel ) { - 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) - - // start service -// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java) - if (videoStreamService == null || videoStreamService?.serviceRunning == false) { - serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java) - serviceIntent?.run { - putExtras(arguments) - action = VideoStreamFloatingWidgetService.ACTION_START_CALL - } - checkFloatingWidgetPermission() - } +// 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) +// +// // start service +//// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java) +// if (videoStreamService == null || videoStreamService?.serviceRunning == false) { +// serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java) +// serviceIntent?.run { +// putExtras(arguments) +// action = VideoStreamFloatingWidgetService.ACTION_START_CALL +// } +// checkFloatingWidgetPermission() +// } } private fun checkFloatingWidgetPermission() { @@ -212,28 +212,29 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, } override fun minimizeVideoEvent(isMinimize: Boolean) { - if (isMinimize) - methodChannel.invokeMethod("onCallConnected", null) - else { - methodChannel.invokeMethod("onCallDisconnected", null) - unbindService() - videoStreamService?.serviceRunning = false - videoStreamService = null - } +// if (isMinimize) +// methodChannel.invokeMethod("onCallConnected", null) +// else { +// methodChannel.invokeMethod("onCallDisconnected", null) +// unbindService() +// videoStreamService?.serviceRunning = false +// videoStreamService = null +// } } override fun onBackPressed() { - if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { - videoStreamService!!.onMinimizedClicked() - } else { - super.onBackPressed() - } + super.onBackPressed() + +// if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { +// videoStreamService!!.onMinimizedClicked() +// } else { +// } } override fun onPause() { - if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { - videoStreamService!!.onMinimizedClicked() - } +// if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { +// videoStreamService!!.onMinimizedClicked() +// } super.onPause() } @@ -248,32 +249,32 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, // } private fun bindService() { - serviceIntent?.run { - if (videoStreamService != null && !videoStreamService!!.serviceRunning) { - startService(this) - } - bindService(this, serviceConnection, Context.BIND_AUTO_CREATE) - } +// serviceIntent?.run { +// if (videoStreamService != null && !videoStreamService!!.serviceRunning) { +// startService(this) +// } +// bindService(this, serviceConnection, Context.BIND_AUTO_CREATE) +// } } private fun unbindService() { - if (bound) { - videoStreamService?.videoCallResponseListener = null // unregister - unbindService(serviceConnection) - bound = false - } +// if (bound) { +// videoStreamService?.videoCallResponseListener = null // unregister +// unbindService(serviceConnection) +// bound = false +// } } private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { -// val binder: VideoStreamContainerService.VideoStreamBinder = -// service as VideoStreamContainerService.VideoStreamBinder - val binder: VideoStreamFloatingWidgetService.VideoStreamBinder = - service as VideoStreamFloatingWidgetService.VideoStreamBinder - videoStreamService = binder.service - bound = true - videoStreamService!!.videoCallResponseListener = this@MainActivity // register - videoStreamService?.serviceRunning = true +//// val binder: VideoStreamContainerService.VideoStreamBinder = +//// service as VideoStreamContainerService.VideoStreamBinder +// val binder: VideoStreamFloatingWidgetService.VideoStreamBinder = +// service as VideoStreamFloatingWidgetService.VideoStreamBinder +// videoStreamService = binder.service +// bound = true +// videoStreamService!!.videoCallResponseListener = this@MainActivity // register +// videoStreamService?.serviceRunning = true } override fun onServiceDisconnected(name: ComponentName?) { diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt index add401ff..9da19a7a 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt @@ -1,91 +1,91 @@ -package com.hmg.hmgDr.Service - -import android.app.Service -import android.content.Intent -import android.os.Binder -import android.os.Bundle -import android.os.IBinder -import com.hmg.hmgDr.MainActivity -import com.hmg.hmgDr.ui.VideoCallResponseListener -import com.hmg.hmgDr.ui.fragment.VideoCallFragment - -class VideoStreamContainerService : Service(), VideoCallResponseListener { - - var videoCallResponseListener: VideoCallResponseListener? = null - var mActivity: MainActivity? = null - set(value) { - field = value - if (field != null) { - setDialogFragment() - } - } - var arguments: Bundle? = null - var serviceRunning: Boolean = false - - - private val serviceBinder: IBinder = VideoStreamBinder() - private var dialogFragment: VideoCallFragment? = null - - override fun onBind(intent: Intent?): IBinder { - return serviceBinder - } - - private fun setDialogFragment() { - mActivity?.run { - if (dialogFragment == null) { - val transaction = supportFragmentManager.beginTransaction() - dialogFragment = VideoCallFragment.newInstance(arguments!!) - dialogFragment?.let { - it.setCallListener(this@VideoStreamContainerService) - it.isCancelable = true - if (it.isAdded) { - it.dismiss() - } else { - it.show(transaction, "dialog") - } - } - } else if (!dialogFragment!!.isVisible) { - val transaction = supportFragmentManager.beginTransaction() - dialogFragment!!.show(transaction, "dialog") - } else { - // don't do anything - } - } - } - - fun closeVideoCall(){ - dialogFragment?.onCallClicked() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent != null && intent.extras != null) { - arguments = intent.extras - } -// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show() - return START_STICKY - } - - override fun onDestroy() { - super.onDestroy() -// Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show() - } - - inner class VideoStreamBinder : Binder() { - val service: VideoStreamContainerService - get() = this@VideoStreamContainerService - } - - override fun onCallFinished(resultCode: Int, intent: Intent?) { - dialogFragment = null - videoCallResponseListener?.onCallFinished(resultCode, intent) - } - - override fun errorHandle(message: String) { - dialogFragment = null -// Toast.makeText(this, message, Toast.LENGTH_LONG).show() - } - - override fun minimizeVideoEvent(isMinimize: Boolean) { - videoCallResponseListener?.minimizeVideoEvent(isMinimize) - } -} \ No newline at end of file +//package com.hmg.hmgDr.Service +// +//import android.app.Service +//import android.content.Intent +//import android.os.Binder +//import android.os.Bundle +//import android.os.IBinder +//import com.hmg.hmgDr.MainActivity +////import com.hmg.hmgDr.ui.VideoCallResponseListener +////import com.hmg.hmgDr.ui.fragment.VideoCallFragment +// +//class VideoStreamContainerService : Service(), VideoCallResponseListener { +// +//// var videoCallResponseListener: VideoCallResponseListener? = null +//// var mActivity: MainActivity? = null +//// set(value) { +//// field = value +//// if (field != null) { +//// setDialogFragment() +//// } +//// } +//// var arguments: Bundle? = null +//// var serviceRunning: Boolean = false +//// +//// +//// private val serviceBinder: IBinder = VideoStreamBinder() +//// private var dialogFragment: VideoCallFragment? = null +//// +//// override fun onBind(intent: Intent?): IBinder { +//// return serviceBinder +//// } +//// +//// private fun setDialogFragment() { +//// mActivity?.run { +//// if (dialogFragment == null) { +//// val transaction = supportFragmentManager.beginTransaction() +//// dialogFragment = VideoCallFragment.newInstance(arguments!!) +//// dialogFragment?.let { +//// it.setCallListener(this@VideoStreamContainerService) +//// it.isCancelable = true +//// if (it.isAdded) { +//// it.dismiss() +//// } else { +//// it.show(transaction, "dialog") +//// } +//// } +//// } else if (!dialogFragment!!.isVisible) { +//// val transaction = supportFragmentManager.beginTransaction() +//// dialogFragment!!.show(transaction, "dialog") +//// } else { +//// // don't do anything +//// } +//// } +//// } +//// +//// fun closeVideoCall(){ +//// dialogFragment?.onCallClicked() +//// } +//// +//// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { +//// if (intent != null && intent.extras != null) { +//// arguments = intent.extras +//// } +////// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show() +//// return START_STICKY +//// } +//// +//// override fun onDestroy() { +//// super.onDestroy() +////// Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show() +//// } +//// +//// inner class VideoStreamBinder : Binder() { +//// val service: VideoStreamContainerService +//// get() = this@VideoStreamContainerService +//// } +//// +//// override fun onCallFinished(resultCode: Int, intent: Intent?) { +//// dialogFragment = null +//// videoCallResponseListener?.onCallFinished(resultCode, intent) +//// } +//// +//// override fun errorHandle(message: String) { +//// dialogFragment = null +////// Toast.makeText(this, message, Toast.LENGTH_LONG).show() +//// } +//// +//// override fun minimizeVideoEvent(isMinimize: Boolean) { +//// videoCallResponseListener?.minimizeVideoEvent(isMinimize) +//// } +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt index 8ece1bd5..ab74cd1c 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt @@ -1,1062 +1,1062 @@ -package com.hmg.hmgDr.Service - -import android.annotation.SuppressLint -import android.app.* -import android.content.Intent -import android.graphics.BitmapFactory -import android.opengl.GLSurfaceView -import android.os.* -import android.util.Log -import android.view.* -import android.widget.* -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat -import androidx.core.view.GestureDetectorCompat -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.Model.* -import com.hmg.hmgDr.ui.VideoCallContract -import com.hmg.hmgDr.ui.VideoCallPresenterImpl -import com.hmg.hmgDr.ui.VideoCallResponseListener -import com.hmg.hmgDr.util.DateUtils -import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer -import com.hmg.hmgDr.util.NotificationUtil -import com.hmg.hmgDr.util.ViewsUtil -import com.hmg.hmgDr.util.audio.CustomAudioDevice -import com.opentok.android.* -import java.util.* - - -class VideoStreamFloatingWidgetService : BaseMovingFloatingWidget(), Session.SessionListener, - PublisherKit.PublisherListener, - SubscriberKit.VideoListener, VideoCallContract.VideoCallView { - - companion object { - @JvmStatic - - private val TAG = VideoStreamFloatingWidgetService::class.java.simpleName - - const val CHANNEL_DEFAULT_IMPORTANCE = "Video_stream_channel" - const val CHANNEL_DEFAULT_NAME = "Video cAll" - const val ONGOING_NOTIFICATION_ID = 1 - - const val ACTION_START_CALL = "com.hmg.hmgDr.Service.action.startCall" - const val ACTION_MINIMIZE_CALL = "com.hmg.hmgDr.Service.action.minimizeCall" - const val ACTION_END_CALL = "com.hmg.hmgDr.Service.action.endCall" - const val ACTION_CHANGE_EXPANDED_COLLAPSED = - "com.hmg.hmgDr.Service.action.changeExpandedCollapsed" - const val NOTIFICATION_IS_EXPANDED = "is_expanded" - } - - var arguments: Bundle? = null - var serviceRunning: Boolean = false - - private val serviceBinder: IBinder = VideoStreamBinder() - private lateinit var videoCallPresenter: VideoCallContract.VideoCallPresenter - var videoCallResponseListener: VideoCallResponseListener? = null - - private lateinit var recordContainer: FrameLayout - private lateinit var thumbnail_container: FrameLayout - private lateinit var activity_clingo_video_call: RelativeLayout - 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 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 tvTimer: TextView -// private lateinit var cmTimer: Chronometer - - 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 var isConnected = false - - private var mCallTimerHandler: Handler? = null - private var mCallTimerRunnable: Runnable? = null - private var mCallFirstTime: Date = Date() - - private var sessionStatusModel: GetSessionStatusModel? = null - - 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 isRecording: Boolean = true - - private var isSwitchCameraClicked = false - private var isCameraClicked = false - private var isSpeckerClicked = false - private var isMicClicked = false - private var elapsedTime: Long = 0 - private var formattedCallTime: String = "00:00" - private lateinit var notificationData: NotificationVideoModel - - var isFullScreen: Boolean = true - private var isCircle: Boolean = false - lateinit var customAudioDevice: CustomAudioDevice - - // Notification variables - private var mNotificationManagerCompat: NotificationManagerCompat? = null - private lateinit var notificationCompatBuilder: NotificationCompat.Builder - - override fun onBind(intent: Intent?): IBinder { - return serviceBinder - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent != null) { - - val action = intent.action - - if (action == ACTION_START_CALL) { - if (intent.extras != null) { - arguments = intent.extras - arguments?.run { - apiKey = getString("apiKey") - sessionId = getString("sessionId") - token = getString("token") - appLang = getString("appLang") - baseUrl = getString("baseUrl") - sessionStatusModel = getParcelable("sessionStatusModel") - if (sessionStatusModel != null) - isRecording = sessionStatusModel!!.isRecording - } - - addFloatingWidgetView() - handleDragDialog() - addForegroundService() - } - } else if (action == ACTION_END_CALL) { - closeVideoCall() - } else if (action == ACTION_MINIMIZE_CALL) { - if (!isFullScreen) - onMinimizedClicked() - } else if (action == ACTION_CHANGE_EXPANDED_COLLAPSED) { - val isExpanded = intent.extras!!.getBoolean(NOTIFICATION_IS_EXPANDED) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // No use channel importance - if (isExpanded) { - notificationCompatBuilder.priority = Notification.PRIORITY_LOW - } else { - notificationCompatBuilder.priority = Notification.PRIORITY_HIGH - } - } else { - if (isExpanded) { - notificationCompatBuilder.priority = Notification.PRIORITY_LOW - } else { - notificationCompatBuilder.priority = Notification.PRIORITY_HIGH - } - } - mNotificationManagerCompat?.notify( - ONGOING_NOTIFICATION_ID, - notificationCompatBuilder.build() - ) - } - - } - return START_STICKY - } - - inner class VideoStreamBinder : Binder() { - val service: VideoStreamFloatingWidgetService - get() = this@VideoStreamFloatingWidgetService - } - - override fun onDestroy() { - try { - mWindowManager?.removeView(floatingWidgetView) - floatingWidgetView = null - mSession = null - mWindowManager = null - - } catch (e: Exception) { - Log.e("onDestroyService", "${e.localizedMessage}.") - } - super.onDestroy() - } - - private fun stopService() { - AudioDeviceManager.getAudioDevice().onPause() - - mCallTimerRunnable?.let { - mCallTimerHandler?.removeCallbacks(it) - mCallTimerHandler = null - mCallTimerRunnable = null - } - - // because problem that timer still continue longer a bit than service so notification called again - mNotificationManagerCompat = null - stopForeground(true) - stopSelf() - videoCallResponseListener?.minimizeVideoEvent(false) - try { - mWindowManager?.removeView(floatingWidgetView) - } catch (e: Exception) { - Log.e("stopService", "${e.localizedMessage}.") - } - } - - override fun addFloatingWidgetView() { - super.addFloatingWidgetView() - - init(floatingWidgetView!!) - - //Add the view to the window - mWindowManager?.addView(floatingWidgetView, windowManagerParams) - } - - @SuppressLint("ClickableViewAccessibility", "RestrictedApi") - private fun init(view: View) { - initUI(view) - - patientName.text = sessionStatusModel!!.patientName - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - - videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) - - checkClientConnected() - setCallStartTimer() - handleVideoViewHeight() - - mDetector = GestureDetectorCompat( - this, - MyGestureListener( - { showControlPanelTemporarily() }, - { miniCircleDoubleTap() }) - ) - try { - // Add a custom audio device before session initialization, - // so when the service is destroyed it will not be errors that receivers is still in memory - customAudioDevice = CustomAudioDevice(this) - customAudioDevice.setRendererMute(false) - if (AudioDeviceManager.getAudioDevice() == null) { - AudioDeviceManager.setAudioDevice(customAudioDevice) - } else { - AudioDeviceManager.getAudioDevice().onResume() - } - - mSession = Session.Builder(this, apiKey, sessionId).build() - mSession!!.setSessionListener(this) - mSession!!.connect(token) - mSession!!.setReconnectionListener(object : Session.ReconnectionListener { - override fun onReconnecting(session: Session?) { - - } - - override fun onReconnected(session: Session?) { - session?.connect(token) - session?.onResume() - } - }) - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun initUI(view: View) { - videoCallContainer = view.findViewById(R.id.video_call_ll) - floatingViewContainer = videoCallContainer - - layoutName = view.findViewById(R.id.layout_name) as RelativeLayout - layoutMini = view.findViewById(R.id.layout_mini) - icMini = view.findViewById(R.id.ic_mini) - recordContainer = view.findViewById(R.id.record_container) - activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) - - 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) - tvTimer = view.findViewById(R.id.tv_timer) - - controlPanel = view.findViewById(R.id.control_panel) - mCallBtn = view.findViewById(R.id.btn_call) - btnMinimize = view.findViewById(R.id.btn_minimize) - mCameraBtn = view.findViewById(R.id.btn_camera) - mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) - mspeckerBtn = view.findViewById(R.id.btn_specker) - mMicBtn = view.findViewById(R.id.btn_mic) - - mCallBtn.setOnClickListener { - onCallClicked() - } - btnMinimize.setOnClickListener { - onMinimizedClicked() - } - mCameraBtn.setOnClickListener { - onCameraClicked(it) - } - mSwitchCameraBtn.setOnClickListener { - onSwitchCameraClicked(it) - } - mspeckerBtn.setOnClickListener { - onSpeckerClicked(it) - } - mMicBtn.setOnClickListener { - onMicClicked(it) - } - icMini.setOnClickListener { - onMiniCircleClicked() - } - } - - private fun checkClientConnected() { - mConnectedHandler = Handler((Looper.getMainLooper())) - mConnectedRunnable = Runnable { - if (!isConnected) { - videoCallPresenter.callClintConnected(sessionStatusModel) - } - } - mConnectedHandler!!.postDelayed( - mConnectedRunnable!!, - (55 * 1000).toLong() - ) - } - - private fun setCallStartTimer() { - mCallTimerHandler = Handler((Looper.getMainLooper())) - mCallTimerRunnable = Runnable { - formattedCallTime = DateUtils.differentDateTimeBetweenDateAndNow(mCallFirstTime) - tvTimer.text = formattedCallTime - - // for change notification timer - if (mNotificationManagerCompat != null) { - notificationData.mSummaryText = formattedCallTime - val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) - notificationCompatBuilder.setStyle(bigTextStyle) - mNotificationManagerCompat?.notify( - ONGOING_NOTIFICATION_ID, - notificationCompatBuilder.build() - ) - } - mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) - } - - } - - private fun handleVideoViewHeight() { - val layoutNameParam: ConstraintLayout.LayoutParams = - layoutName.layoutParams as ConstraintLayout.LayoutParams - val layoutMiniParam: ConstraintLayout.LayoutParams = - layoutMini.layoutParams as ConstraintLayout.LayoutParams - val controlPanelParam: ConstraintLayout.LayoutParams = - controlPanel.layoutParams as ConstraintLayout.LayoutParams - - val layoutNameHeight: Int = - resources.getDimension(R.dimen.layout_name_height).toInt() - val layoutMiniHeight: Int = - resources.getDimension(R.dimen.layout_mini_height).toInt() - val panelHeight: Int = resources.getDimension(R.dimen.layout_panel_height).toInt() - val panelHeightSmall: Int = - resources.getDimension(R.dimen.layout_panel_height_small).toInt() - - val panelPadding: Int = - resources.getDimension(R.dimen.padding_space_big).toInt() - val panelPaddingMedium: Int = - resources.getDimension(R.dimen.padding_space_medium).toInt() - - val temp = ViewsUtil.getStatusBarHeight(applicationContext) / 2 - - val screenWidth: Float - val screenHeight: Float - - if (isFullScreen) { - screenWidth = ViewsUtil.getWidthDp(this) - screenHeight = ViewsUtil.getHeightDp(this) - - layoutNameParam.height = layoutNameHeight + temp - layoutMiniParam.height = 0 - controlPanelParam.height = panelHeight + temp - - controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) - } else { - - if (isCircle) { - screenWidth = 300F - screenHeight = 300F - - layoutNameParam.height = 0 - layoutMiniParam.height = 0 - controlPanelParam.height = 0 - } else { - screenWidth = 400F - screenHeight = 600F - - layoutNameParam.height = 0 - layoutMiniParam.height = layoutMiniHeight - controlPanelParam.height = panelHeightSmall - } - - controlPanel.setPadding( - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium - ) - } - - layoutName.layoutParams = layoutNameParam - layoutMini.layoutParams = layoutMiniParam - controlPanel.layoutParams = controlPanelParam - - var videoStreamHeight = - screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height - - if (isFullScreen) { -// videoStreamHeight -= getStatusBarHeight() / 2 - } - - val callLayoutParam: ConstraintLayout.LayoutParams = - activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams - - callLayoutParam.height = videoStreamHeight.toInt() - callLayoutParam.width = screenWidth.toInt() - } - - private fun setViewsVisibility() { - val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = - btnMinimize.layoutParams as ConstraintLayout.LayoutParams - val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = - mCallBtn.layoutParams as ConstraintLayout.LayoutParams - - val iconSize: Int = resources.getDimension(R.dimen.video_icon_size).toInt() - val iconSizeSmall: Int = - resources.getDimension(R.dimen.video_icon_size_small).toInt() - - val localPreviewMargin: Int = - resources.getDimension(R.dimen.local_preview_margin_top).toInt() - val localPreviewWidth: Int = - resources.getDimension(R.dimen.local_preview_width).toInt() - val localPreviewHeight: Int = - resources.getDimension(R.dimen.local_preview_height).toInt() - val localPreviewLayoutParam: RelativeLayout.LayoutParams = - mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams - - val remotePreviewIconSize: Int = - resources.getDimension(R.dimen.remote_back_icon_size).toInt() - val remotePreviewIconSizeSmall: Int = - 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) - if (mPublisher != null && mPublisher!!.view.parent == null) { - mPublisherViewContainer.addView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.VISIBLE - -// 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) - - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.GONE -// 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 - - handleVideoViewHeight() - } - - @SuppressLint("ClickableViewAccessibility") - private fun handleDragDialog() { - getWindowManagerDefaultDisplay() - - videoCallContainer.setOnTouchListener(dragListener) - mSubscriberViewContainer.setOnTouchListener(dragListener) - } - - /*** - * Click Listener - */ - - fun onCallClicked() { - disconnectSession() - } - - fun onMinimizedClicked() { - if (isCircle) { - onMiniCircleClicked() - } - if (isFullScreen) { - windowManagerParams.width = 400 - windowManagerParams.height = 600 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - recordContainer.visibility = View.GONE - } else { - windowManagerParams.width = WindowManager.LayoutParams.MATCH_PARENT - windowManagerParams.height = WindowManager.LayoutParams.MATCH_PARENT - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - } - isFullScreen = !isFullScreen - - val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand - btnMinimize.setImageResource(res) - setViewsVisibility() - -// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) - } - - 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 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) - } - } - - 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) - } - } - - 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 onMiniCircleClicked() { - if (isCircle) { - windowManagerParams.width = 400 - windowManagerParams.height = 600 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - } else { - windowManagerParams.width = 300 - windowManagerParams.height = 300 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - } - isCircle = !isCircle - - - if (mSubscriber != null) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) - } else { - if (isCircle) { - videoCallContainer.background = - ContextCompat.getDrawable(this, R.drawable.circle_shape) - mSubscriberViewContainer.background = - ContextCompat.getDrawable(this, R.drawable.circle_shape) - } else { - videoCallContainer.setBackgroundColor( - ContextCompat.getColor( - this, - R.color.text_color - ) - ) - mSubscriberViewContainer.setBackgroundColor( - ContextCompat.getColor( - this, - R.color.remoteBackground - ) - ) - } - } - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - - handleVideoViewHeight() - } - - private fun showControlPanelTemporarily() { - if (!isCircle) { - controlPanel.visibility = View.VISIBLE - mVolHandler!!.removeCallbacks(mVolRunnable!!) - mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) - } - } - - private fun miniCircleDoubleTap() { - if (isCircle) { - onMiniCircleClicked() - } - } - - fun closeVideoCall() { - onCallClicked() - } - - /*** - * Session Listener - */ - - override fun onConnected(session: Session?) { - Log.i(TAG, "Session Connected") - mPublisher = Publisher.Builder(this) -// .name("publisher") -// .renderer(ThumbnailCircleVideoRenderer(requireContext())) - .build() - mPublisher!!.setPublisherListener(this) - mPublisher!!.audioFallbackEnabled = false - if (mPublisher!!.view is GLSurfaceView) { - (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) - } - - mPublisherViewContainer.addView(mPublisher!!.view) - - mSession!!.publish(mPublisher) - - // start call timer to show on top - mCallFirstTime = Date() - mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) - - 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) - } - - 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() - } - - private fun disconnectSession() { - if (mSession == null) { - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) - stopService() - 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() - - videoCallPresenter.callChangeCallStatus( - ChangeCallStatusRequestModel( - 16, - sessionStatusModel!!.doctorId, - sessionStatusModel!!.generalid, - token, - sessionStatusModel!!.vcid - ) - ) -// stopService() - onCallChangeCallStatusSuccessful() - } - - private fun subscribeToStream(stream: Stream) { - mSubscriber = Subscriber.Builder(this, stream) - .renderer(DynamicVideoRenderer(this)) - .build() - mSubscriber!!.setVideoListener(this) - mSession!!.subscribe(mSubscriber) - } - - /** - * Publish Listener - */ - - 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(TAG, "onError: Error (" + opentokError.message + ") in publisher") - // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") -// dialog?.dismiss() - } - - /** - * Video Listener - */ - - override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { - if (mSubscriber == null) { - return - } - mSubscriber!!.setStyle( - BaseVideoRenderer.STYLE_VIDEO_SCALE, - BaseVideoRenderer.STYLE_VIDEO_FILL - ) - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) - mSubscriberViewContainer.addView(mSubscriber!!.view) -// switchToThumbnailCircle() - } - - override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(TAG, "onVideoDisabled: Error ($s)") - -// 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.remoteBackground)) -// } - } - - override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(TAG, "onVideoEnabled: Error ($s)") - -// if (mSubscriber != null) { -// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) -// } - } - - override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} - - override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} - - private 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) - } - - private 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) - } - - /** - * Video call viewListener - */ - - override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { - if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { - val returnIntent = Intent() - returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) - disconnectSession() - videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) - stopService() - } - } - - private fun onCallChangeCallStatusSuccessful() { - val returnIntent = Intent() - returnIntent.putExtra("CallEnd", sessionStatusModel) - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) - stopService() - } - - override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} - - override fun onFailure() {} - - /*** - * Notification methods - */ - - private fun addForegroundService() { - mNotificationManagerCompat = NotificationManagerCompat.from(applicationContext) - val areNotificationsEnabled = mNotificationManagerCompat!!.areNotificationsEnabled() - if (!areNotificationsEnabled) { - Toast.makeText( - this, - "You need to enable notifications for this app", - Toast.LENGTH_SHORT - ).show() - // Links to this app's notification settings - NotificationUtil.openNotificationSettingsForApp(applicationContext) - return - } - generateBigTextStyleNotification() - } - - private fun generateBigTextStyleNotification() { - notificationData = - NotificationVideoModel( - sessionStatusModel!!.patientName, - "Tap to return to call", - CHANNEL_DEFAULT_IMPORTANCE, - CHANNEL_DEFAULT_NAME, - "Video call stream background", - mSummaryText = formattedCallTime - ) - // 1. Create/Retrieve Notification Channel for O and beyond devices (26+). - val notificationChannelId: String = - NotificationUtil.createNotificationChannel(this, notificationData) - - // 2. Build the BIG_TEXT_STYLE. - val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) - - // 3. Set up main Intent for notification. - val pendingIntent: PendingIntent = - Intent(this, VideoStreamFloatingWidgetService::class.java) - .let { notificationIntent -> - notificationIntent.action = ACTION_MINIMIZE_CALL - PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE ) - } - - // 4. Create additional Actions (Intents) for the Notification. - // Dismiss Action. - val endCallPendingIntent: PendingIntent = - Intent(this, VideoStreamFloatingWidgetService::class.java).apply { - action = ACTION_END_CALL - } - .let { notificationIntent -> - PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE) - } - val endCallAction = NotificationCompat.Action.Builder( - R.drawable.ic_end_call, - "End Call", - endCallPendingIntent - ) - .build() - - // 5. Build and issue the notification. - // Notification Channel Id is ignored for Android pre O (26). - notificationCompatBuilder = notificationChannelId.let { - NotificationCompat.Builder( - applicationContext, it - ) - } - - notificationCompatBuilder - // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after). - .setStyle(bigTextStyle) - // Title for API <16 (4.0 and below) devices. - .setContentTitle(notificationData.mBigContentTitle) - // Content for API <24 (7.0 and below) devices. - .setContentText(notificationData.mContentText) - .setSmallIcon(R.mipmap.ic_launcher) - .setLargeIcon( - BitmapFactory.decodeResource( - resources, - R.mipmap.ic_launcher - ) - ) - /*.setCustomContentView(mRemoteViews) - .setCustomBigContentView(mRemoteViewsExpand)*/ - .setContentIntent(pendingIntent) -// .setDefaults(NotificationCompat.DEFAULT_ALL) - // Set primary color (important for Wear 2.0 Notifications). - .setColor(ContextCompat.getColor(applicationContext, R.color.colorPrimary)) - .setCategory(Notification.CATEGORY_SERVICE) - .setPriority(notificationData.mPriority) - .setVisibility(notificationData.mChannelLockscreenVisibility) - .addAction(endCallAction) // for version code < O, or for all versions if RemoteViews not used - .setUsesChronometer(true) - .setWhen(elapsedTime) - .setOnlyAlertOnce(true) // This will ensure that updates to an existing notification won't sound/vibrate https://stackoverflow.com/a/52349466/6246772 - .setSound(null) - .setOngoing(true) - .setCategory(NotificationCompat.CATEGORY_SERVICE) - .setColorized(true) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) //to show content in lock screen - - val notification = notificationCompatBuilder - .build() - - mNotificationManagerCompat!!.notify(ONGOING_NOTIFICATION_ID, notification) - startForeground(ONGOING_NOTIFICATION_ID, notification) - } - -} \ No newline at end of file +//package com.hmg.hmgDr.Service +// +//import android.annotation.SuppressLint +//import android.app.* +//import android.content.Intent +//import android.graphics.BitmapFactory +//import android.opengl.GLSurfaceView +//import android.os.* +//import android.util.Log +//import android.view.* +//import android.widget.* +//import androidx.constraintlayout.widget.ConstraintLayout +//import androidx.core.app.NotificationCompat +//import androidx.core.app.NotificationManagerCompat +//import androidx.core.content.ContextCompat +//import androidx.core.view.GestureDetectorCompat +//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.Model.* +//import com.hmg.hmgDr.ui.VideoCallContract +//import com.hmg.hmgDr.ui.VideoCallPresenterImpl +//import com.hmg.hmgDr.ui.VideoCallResponseListener +//import com.hmg.hmgDr.util.DateUtils +//import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer +//import com.hmg.hmgDr.util.NotificationUtil +//import com.hmg.hmgDr.util.ViewsUtil +//import com.hmg.hmgDr.util.audio.CustomAudioDevice +//import com.opentok.android.* +//import java.util.* +// +// +//class VideoStreamFloatingWidgetService : BaseMovingFloatingWidget(), Session.SessionListener, +// PublisherKit.PublisherListener, +// SubscriberKit.VideoListener, VideoCallContract.VideoCallView { +//// +//// companion object { +//// @JvmStatic +//// +//// private val TAG = VideoStreamFloatingWidgetService::class.java.simpleName +//// +//// const val CHANNEL_DEFAULT_IMPORTANCE = "Video_stream_channel" +//// const val CHANNEL_DEFAULT_NAME = "Video cAll" +//// const val ONGOING_NOTIFICATION_ID = 1 +//// +//// const val ACTION_START_CALL = "com.hmg.hmgDr.Service.action.startCall" +//// const val ACTION_MINIMIZE_CALL = "com.hmg.hmgDr.Service.action.minimizeCall" +//// const val ACTION_END_CALL = "com.hmg.hmgDr.Service.action.endCall" +//// const val ACTION_CHANGE_EXPANDED_COLLAPSED = +//// "com.hmg.hmgDr.Service.action.changeExpandedCollapsed" +//// const val NOTIFICATION_IS_EXPANDED = "is_expanded" +//// } +//// +//// var arguments: Bundle? = null +//// var serviceRunning: Boolean = false +//// +//// private val serviceBinder: IBinder = VideoStreamBinder() +//// private lateinit var videoCallPresenter: VideoCallContract.VideoCallPresenter +//// var videoCallResponseListener: VideoCallResponseListener? = null +//// +//// private lateinit var recordContainer: FrameLayout +//// private lateinit var thumbnail_container: FrameLayout +//// private lateinit var activity_clingo_video_call: RelativeLayout +//// 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 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 tvTimer: TextView +////// private lateinit var cmTimer: Chronometer +//// +//// 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 var isConnected = false +//// +//// private var mCallTimerHandler: Handler? = null +//// private var mCallTimerRunnable: Runnable? = null +//// private var mCallFirstTime: Date = Date() +//// +//// private var sessionStatusModel: GetSessionStatusModel? = null +//// +//// 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 isRecording: Boolean = true +//// +//// private var isSwitchCameraClicked = false +//// private var isCameraClicked = false +//// private var isSpeckerClicked = false +//// private var isMicClicked = false +//// private var elapsedTime: Long = 0 +//// private var formattedCallTime: String = "00:00" +//// private lateinit var notificationData: NotificationVideoModel +//// +//// var isFullScreen: Boolean = true +//// private var isCircle: Boolean = false +//// lateinit var customAudioDevice: CustomAudioDevice +//// +//// // Notification variables +//// private var mNotificationManagerCompat: NotificationManagerCompat? = null +//// private lateinit var notificationCompatBuilder: NotificationCompat.Builder +//// +//// override fun onBind(intent: Intent?): IBinder { +//// return serviceBinder +//// } +//// +//// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { +//// if (intent != null) { +//// +//// val action = intent.action +//// +//// if (action == ACTION_START_CALL) { +//// if (intent.extras != null) { +//// arguments = intent.extras +//// arguments?.run { +//// apiKey = getString("apiKey") +//// sessionId = getString("sessionId") +//// token = getString("token") +//// appLang = getString("appLang") +//// baseUrl = getString("baseUrl") +//// sessionStatusModel = getParcelable("sessionStatusModel") +//// if (sessionStatusModel != null) +//// isRecording = sessionStatusModel!!.isRecording +//// } +//// +//// addFloatingWidgetView() +//// handleDragDialog() +//// addForegroundService() +//// } +//// } else if (action == ACTION_END_CALL) { +//// closeVideoCall() +//// } else if (action == ACTION_MINIMIZE_CALL) { +//// if (!isFullScreen) +//// onMinimizedClicked() +//// } else if (action == ACTION_CHANGE_EXPANDED_COLLAPSED) { +//// val isExpanded = intent.extras!!.getBoolean(NOTIFICATION_IS_EXPANDED) +//// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +//// // No use channel importance +//// if (isExpanded) { +//// notificationCompatBuilder.priority = Notification.PRIORITY_LOW +//// } else { +//// notificationCompatBuilder.priority = Notification.PRIORITY_HIGH +//// } +//// } else { +//// if (isExpanded) { +//// notificationCompatBuilder.priority = Notification.PRIORITY_LOW +//// } else { +//// notificationCompatBuilder.priority = Notification.PRIORITY_HIGH +//// } +//// } +//// mNotificationManagerCompat?.notify( +//// ONGOING_NOTIFICATION_ID, +//// notificationCompatBuilder.build() +//// ) +//// } +//// +//// } +//// return START_STICKY +//// } +//// +//// inner class VideoStreamBinder : Binder() { +//// val service: VideoStreamFloatingWidgetService +//// get() = this@VideoStreamFloatingWidgetService +//// } +//// +//// override fun onDestroy() { +//// try { +//// mWindowManager?.removeView(floatingWidgetView) +//// floatingWidgetView = null +//// mSession = null +//// mWindowManager = null +//// +//// } catch (e: Exception) { +//// Log.e("onDestroyService", "${e.localizedMessage}.") +//// } +//// super.onDestroy() +//// } +//// +//// private fun stopService() { +//// AudioDeviceManager.getAudioDevice().onPause() +//// +//// mCallTimerRunnable?.let { +//// mCallTimerHandler?.removeCallbacks(it) +//// mCallTimerHandler = null +//// mCallTimerRunnable = null +//// } +//// +//// // because problem that timer still continue longer a bit than service so notification called again +//// mNotificationManagerCompat = null +//// stopForeground(true) +//// stopSelf() +//// videoCallResponseListener?.minimizeVideoEvent(false) +//// try { +//// mWindowManager?.removeView(floatingWidgetView) +//// } catch (e: Exception) { +//// Log.e("stopService", "${e.localizedMessage}.") +//// } +//// } +//// +//// override fun addFloatingWidgetView() { +//// super.addFloatingWidgetView() +//// +//// init(floatingWidgetView!!) +//// +//// //Add the view to the window +//// mWindowManager?.addView(floatingWidgetView, windowManagerParams) +//// } +//// +//// @SuppressLint("ClickableViewAccessibility", "RestrictedApi") +//// private fun init(view: View) { +//// initUI(view) +//// +//// patientName.text = sessionStatusModel!!.patientName +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// +//// videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) +//// +//// checkClientConnected() +//// setCallStartTimer() +//// handleVideoViewHeight() +//// +//// mDetector = GestureDetectorCompat( +//// this, +//// MyGestureListener( +//// { showControlPanelTemporarily() }, +//// { miniCircleDoubleTap() }) +//// ) +//// try { +//// // Add a custom audio device before session initialization, +//// // so when the service is destroyed it will not be errors that receivers is still in memory +//// customAudioDevice = CustomAudioDevice(this) +//// customAudioDevice.setRendererMute(false) +//// if (AudioDeviceManager.getAudioDevice() == null) { +//// AudioDeviceManager.setAudioDevice(customAudioDevice) +//// } else { +//// AudioDeviceManager.getAudioDevice().onResume() +//// } +//// +//// mSession = Session.Builder(this, apiKey, sessionId).build() +//// mSession!!.setSessionListener(this) +//// mSession!!.connect(token) +//// mSession!!.setReconnectionListener(object : Session.ReconnectionListener { +//// override fun onReconnecting(session: Session?) { +//// +//// } +//// +//// override fun onReconnected(session: Session?) { +//// session?.connect(token) +//// session?.onResume() +//// } +//// }) +//// } catch (e: Exception) { +//// e.printStackTrace() +//// } +//// } +//// +//// private fun initUI(view: View) { +//// videoCallContainer = view.findViewById(R.id.video_call_ll) +//// floatingViewContainer = videoCallContainer +//// +//// layoutName = view.findViewById(R.id.layout_name) as RelativeLayout +//// layoutMini = view.findViewById(R.id.layout_mini) +//// icMini = view.findViewById(R.id.ic_mini) +//// recordContainer = view.findViewById(R.id.record_container) +//// activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) +//// +//// 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) +//// tvTimer = view.findViewById(R.id.tv_timer) +//// +//// controlPanel = view.findViewById(R.id.control_panel) +//// mCallBtn = view.findViewById(R.id.btn_call) +//// btnMinimize = view.findViewById(R.id.btn_minimize) +//// mCameraBtn = view.findViewById(R.id.btn_camera) +//// mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) +//// mspeckerBtn = view.findViewById(R.id.btn_specker) +//// mMicBtn = view.findViewById(R.id.btn_mic) +//// +//// mCallBtn.setOnClickListener { +//// onCallClicked() +//// } +//// btnMinimize.setOnClickListener { +//// onMinimizedClicked() +//// } +//// mCameraBtn.setOnClickListener { +//// onCameraClicked(it) +//// } +//// mSwitchCameraBtn.setOnClickListener { +//// onSwitchCameraClicked(it) +//// } +//// mspeckerBtn.setOnClickListener { +//// onSpeckerClicked(it) +//// } +//// mMicBtn.setOnClickListener { +//// onMicClicked(it) +//// } +//// icMini.setOnClickListener { +//// onMiniCircleClicked() +//// } +//// } +//// +//// private fun checkClientConnected() { +//// mConnectedHandler = Handler((Looper.getMainLooper())) +//// mConnectedRunnable = Runnable { +//// if (!isConnected) { +//// videoCallPresenter.callClintConnected(sessionStatusModel) +//// } +//// } +//// mConnectedHandler!!.postDelayed( +//// mConnectedRunnable!!, +//// (55 * 1000).toLong() +//// ) +//// } +//// +//// private fun setCallStartTimer() { +//// mCallTimerHandler = Handler((Looper.getMainLooper())) +//// mCallTimerRunnable = Runnable { +//// formattedCallTime = DateUtils.differentDateTimeBetweenDateAndNow(mCallFirstTime) +//// tvTimer.text = formattedCallTime +//// +//// // for change notification timer +//// if (mNotificationManagerCompat != null) { +//// notificationData.mSummaryText = formattedCallTime +//// val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) +//// notificationCompatBuilder.setStyle(bigTextStyle) +//// mNotificationManagerCompat?.notify( +//// ONGOING_NOTIFICATION_ID, +//// notificationCompatBuilder.build() +//// ) +//// } +//// mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) +//// } +//// +//// } +//// +//// private fun handleVideoViewHeight() { +//// val layoutNameParam: ConstraintLayout.LayoutParams = +//// layoutName.layoutParams as ConstraintLayout.LayoutParams +//// val layoutMiniParam: ConstraintLayout.LayoutParams = +//// layoutMini.layoutParams as ConstraintLayout.LayoutParams +//// val controlPanelParam: ConstraintLayout.LayoutParams = +//// controlPanel.layoutParams as ConstraintLayout.LayoutParams +//// +//// val layoutNameHeight: Int = +//// resources.getDimension(R.dimen.layout_name_height).toInt() +//// val layoutMiniHeight: Int = +//// resources.getDimension(R.dimen.layout_mini_height).toInt() +//// val panelHeight: Int = resources.getDimension(R.dimen.layout_panel_height).toInt() +//// val panelHeightSmall: Int = +//// resources.getDimension(R.dimen.layout_panel_height_small).toInt() +//// +//// val panelPadding: Int = +//// resources.getDimension(R.dimen.padding_space_big).toInt() +//// val panelPaddingMedium: Int = +//// resources.getDimension(R.dimen.padding_space_medium).toInt() +//// +//// val temp = ViewsUtil.getStatusBarHeight(applicationContext) / 2 +//// +//// val screenWidth: Float +//// val screenHeight: Float +//// +//// if (isFullScreen) { +//// screenWidth = ViewsUtil.getWidthDp(this) +//// screenHeight = ViewsUtil.getHeightDp(this) +//// +//// layoutNameParam.height = layoutNameHeight + temp +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = panelHeight + temp +//// +//// controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) +//// } else { +//// +//// if (isCircle) { +//// screenWidth = 300F +//// screenHeight = 300F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = 0 +//// } else { +//// screenWidth = 400F +//// screenHeight = 600F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = layoutMiniHeight +//// controlPanelParam.height = panelHeightSmall +//// } +//// +//// controlPanel.setPadding( +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium +//// ) +//// } +//// +//// layoutName.layoutParams = layoutNameParam +//// layoutMini.layoutParams = layoutMiniParam +//// controlPanel.layoutParams = controlPanelParam +//// +//// var videoStreamHeight = +//// screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height +//// +//// if (isFullScreen) { +////// videoStreamHeight -= getStatusBarHeight() / 2 +//// } +//// +//// val callLayoutParam: ConstraintLayout.LayoutParams = +//// activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams +//// +//// callLayoutParam.height = videoStreamHeight.toInt() +//// callLayoutParam.width = screenWidth.toInt() +//// } +//// +//// private fun setViewsVisibility() { +//// val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = +//// btnMinimize.layoutParams as ConstraintLayout.LayoutParams +//// val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = +//// mCallBtn.layoutParams as ConstraintLayout.LayoutParams +//// +//// val iconSize: Int = resources.getDimension(R.dimen.video_icon_size).toInt() +//// val iconSizeSmall: Int = +//// resources.getDimension(R.dimen.video_icon_size_small).toInt() +//// +//// val localPreviewMargin: Int = +//// resources.getDimension(R.dimen.local_preview_margin_top).toInt() +//// val localPreviewWidth: Int = +//// resources.getDimension(R.dimen.local_preview_width).toInt() +//// val localPreviewHeight: Int = +//// resources.getDimension(R.dimen.local_preview_height).toInt() +//// val localPreviewLayoutParam: RelativeLayout.LayoutParams = +//// mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams +//// +//// val remotePreviewIconSize: Int = +//// resources.getDimension(R.dimen.remote_back_icon_size).toInt() +//// val remotePreviewIconSizeSmall: Int = +//// 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) +//// if (mPublisher != null && mPublisher!!.view.parent == null) { +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.VISIBLE +//// +////// 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) +//// +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.GONE +////// 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 +//// +//// handleVideoViewHeight() +//// } +//// +//// @SuppressLint("ClickableViewAccessibility") +//// private fun handleDragDialog() { +//// getWindowManagerDefaultDisplay() +//// +//// videoCallContainer.setOnTouchListener(dragListener) +//// mSubscriberViewContainer.setOnTouchListener(dragListener) +//// } +//// +//// /*** +//// * Click Listener +//// */ +//// +//// fun onCallClicked() { +//// disconnectSession() +//// } +//// +//// fun onMinimizedClicked() { +//// if (isCircle) { +//// onMiniCircleClicked() +//// } +//// if (isFullScreen) { +//// windowManagerParams.width = 400 +//// windowManagerParams.height = 600 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// recordContainer.visibility = View.GONE +//// } else { +//// windowManagerParams.width = WindowManager.LayoutParams.MATCH_PARENT +//// windowManagerParams.height = WindowManager.LayoutParams.MATCH_PARENT +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// } +//// isFullScreen = !isFullScreen +//// +//// val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand +//// btnMinimize.setImageResource(res) +//// setViewsVisibility() +//// +////// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) +//// } +//// +//// 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 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) +//// } +//// } +//// +//// 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) +//// } +//// } +//// +//// 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 onMiniCircleClicked() { +//// if (isCircle) { +//// windowManagerParams.width = 400 +//// windowManagerParams.height = 600 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// } else { +//// windowManagerParams.width = 300 +//// windowManagerParams.height = 300 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// } +//// isCircle = !isCircle +//// +//// +//// if (mSubscriber != null) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +//// } else { +//// if (isCircle) { +//// videoCallContainer.background = +//// ContextCompat.getDrawable(this, R.drawable.circle_shape) +//// mSubscriberViewContainer.background = +//// ContextCompat.getDrawable(this, R.drawable.circle_shape) +//// } else { +//// videoCallContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// this, +//// R.color.text_color +//// ) +//// ) +//// mSubscriberViewContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// this, +//// R.color.remoteBackground +//// ) +//// ) +//// } +//// } +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// +//// handleVideoViewHeight() +//// } +//// +//// private fun showControlPanelTemporarily() { +//// if (!isCircle) { +//// controlPanel.visibility = View.VISIBLE +//// mVolHandler!!.removeCallbacks(mVolRunnable!!) +//// mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) +//// } +//// } +//// +//// private fun miniCircleDoubleTap() { +//// if (isCircle) { +//// onMiniCircleClicked() +//// } +//// } +//// +//// fun closeVideoCall() { +//// onCallClicked() +//// } +//// +//// /*** +//// * Session Listener +//// */ +//// +//// override fun onConnected(session: Session?) { +//// Log.i(TAG, "Session Connected") +//// mPublisher = Publisher.Builder(this) +////// .name("publisher") +////// .renderer(ThumbnailCircleVideoRenderer(requireContext())) +//// .build() +//// mPublisher!!.setPublisherListener(this) +//// mPublisher!!.audioFallbackEnabled = false +//// if (mPublisher!!.view is GLSurfaceView) { +//// (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) +//// } +//// +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// +//// mSession!!.publish(mPublisher) +//// +//// // start call timer to show on top +//// mCallFirstTime = Date() +//// mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) +//// +//// 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) +//// } +//// +//// 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() +//// } +//// +//// private fun disconnectSession() { +//// if (mSession == null) { +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) +//// stopService() +//// 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() +//// +//// videoCallPresenter.callChangeCallStatus( +//// ChangeCallStatusRequestModel( +//// 16, +//// sessionStatusModel!!.doctorId, +//// sessionStatusModel!!.generalid, +//// token, +//// sessionStatusModel!!.vcid +//// ) +//// ) +////// stopService() +//// onCallChangeCallStatusSuccessful() +//// } +//// +//// private fun subscribeToStream(stream: Stream) { +//// mSubscriber = Subscriber.Builder(this, stream) +//// .renderer(DynamicVideoRenderer(this)) +//// .build() +//// mSubscriber!!.setVideoListener(this) +//// mSession!!.subscribe(mSubscriber) +//// } +//// +//// /** +//// * Publish Listener +//// */ +//// +//// 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(TAG, "onError: Error (" + opentokError.message + ") in publisher") +//// // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") +////// dialog?.dismiss() +//// } +//// +//// /** +//// * Video Listener +//// */ +//// +//// override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { +//// if (mSubscriber == null) { +//// return +//// } +//// mSubscriber!!.setStyle( +//// BaseVideoRenderer.STYLE_VIDEO_SCALE, +//// BaseVideoRenderer.STYLE_VIDEO_FILL +//// ) +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) +//// mSubscriberViewContainer.addView(mSubscriber!!.view) +////// switchToThumbnailCircle() +//// } +//// +//// override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(TAG, "onVideoDisabled: Error ($s)") +//// +////// 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.remoteBackground)) +////// } +//// } +//// +//// override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(TAG, "onVideoEnabled: Error ($s)") +//// +////// if (mSubscriber != null) { +////// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +////// } +//// } +//// +//// override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} +//// +//// override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} +//// +//// private 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) +//// } +//// +//// private 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) +//// } +//// +//// /** +//// * Video call viewListener +//// */ +//// +//// override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { +//// if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { +//// val returnIntent = Intent() +//// returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) +//// disconnectSession() +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) +//// stopService() +//// } +//// } +//// +//// private fun onCallChangeCallStatusSuccessful() { +//// val returnIntent = Intent() +//// returnIntent.putExtra("CallEnd", sessionStatusModel) +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) +//// stopService() +//// } +//// +//// override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} +//// +//// override fun onFailure() {} +//// +//// /*** +//// * Notification methods +//// */ +//// +//// private fun addForegroundService() { +//// mNotificationManagerCompat = NotificationManagerCompat.from(applicationContext) +//// val areNotificationsEnabled = mNotificationManagerCompat!!.areNotificationsEnabled() +//// if (!areNotificationsEnabled) { +//// Toast.makeText( +//// this, +//// "You need to enable notifications for this app", +//// Toast.LENGTH_SHORT +//// ).show() +//// // Links to this app's notification settings +//// NotificationUtil.openNotificationSettingsForApp(applicationContext) +//// return +//// } +//// generateBigTextStyleNotification() +//// } +//// +//// private fun generateBigTextStyleNotification() { +//// notificationData = +//// NotificationVideoModel( +//// sessionStatusModel!!.patientName, +//// "Tap to return to call", +//// CHANNEL_DEFAULT_IMPORTANCE, +//// CHANNEL_DEFAULT_NAME, +//// "Video call stream background", +//// mSummaryText = formattedCallTime +//// ) +//// // 1. Create/Retrieve Notification Channel for O and beyond devices (26+). +//// val notificationChannelId: String = +//// NotificationUtil.createNotificationChannel(this, notificationData) +//// +//// // 2. Build the BIG_TEXT_STYLE. +//// val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) +//// +//// // 3. Set up main Intent for notification. +//// val pendingIntent: PendingIntent = +//// Intent(this, VideoStreamFloatingWidgetService::class.java) +//// .let { notificationIntent -> +//// notificationIntent.action = ACTION_MINIMIZE_CALL +//// PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE ) +//// } +//// +//// // 4. Create additional Actions (Intents) for the Notification. +//// // Dismiss Action. +//// val endCallPendingIntent: PendingIntent = +//// Intent(this, VideoStreamFloatingWidgetService::class.java).apply { +//// action = ACTION_END_CALL +//// } +//// .let { notificationIntent -> +//// PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE) +//// } +//// val endCallAction = NotificationCompat.Action.Builder( +//// R.drawable.ic_end_call, +//// "End Call", +//// endCallPendingIntent +//// ) +//// .build() +//// +//// // 5. Build and issue the notification. +//// // Notification Channel Id is ignored for Android pre O (26). +//// notificationCompatBuilder = notificationChannelId.let { +//// NotificationCompat.Builder( +//// applicationContext, it +//// ) +//// } +//// +//// notificationCompatBuilder +//// // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after). +//// .setStyle(bigTextStyle) +//// // Title for API <16 (4.0 and below) devices. +//// .setContentTitle(notificationData.mBigContentTitle) +//// // Content for API <24 (7.0 and below) devices. +//// .setContentText(notificationData.mContentText) +//// .setSmallIcon(R.mipmap.ic_launcher) +//// .setLargeIcon( +//// BitmapFactory.decodeResource( +//// resources, +//// R.mipmap.ic_launcher +//// ) +//// ) +//// /*.setCustomContentView(mRemoteViews) +//// .setCustomBigContentView(mRemoteViewsExpand)*/ +//// .setContentIntent(pendingIntent) +////// .setDefaults(NotificationCompat.DEFAULT_ALL) +//// // Set primary color (important for Wear 2.0 Notifications). +//// .setColor(ContextCompat.getColor(applicationContext, R.color.colorPrimary)) +//// .setCategory(Notification.CATEGORY_SERVICE) +//// .setPriority(notificationData.mPriority) +//// .setVisibility(notificationData.mChannelLockscreenVisibility) +//// .addAction(endCallAction) // for version code < O, or for all versions if RemoteViews not used +//// .setUsesChronometer(true) +//// .setWhen(elapsedTime) +//// .setOnlyAlertOnce(true) // This will ensure that updates to an existing notification won't sound/vibrate https://stackoverflow.com/a/52349466/6246772 +//// .setSound(null) +//// .setOngoing(true) +//// .setCategory(NotificationCompat.CATEGORY_SERVICE) +//// .setColorized(true) +//// .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) //to show content in lock screen +//// +//// val notification = notificationCompatBuilder +//// .build() +//// +//// mNotificationManagerCompat!!.notify(ONGOING_NOTIFICATION_ID, notification) +//// startForeground(ONGOING_NOTIFICATION_ID, notification) +//// } +// +//} \ 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 index 2ed27dab..ddc967ea 100644 --- 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 @@ -1,1176 +1,1176 @@ -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.appcompat.app.AlertDialog -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.opentok.DynamicVideoRenderer -import com.hmg.hmgDr.util.ViewsUtil -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 - -// check this if it works to solve keyboard not work when dialog is opened -// https://stackoverflow.com/questions/55066977/how-to-prevent-custom-dialogfragment-from-hiding-keyboard-when-being-shown -class VideoCallFragment : DialogFragment(), 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 recordContainer: FrameLayout - private lateinit var thumbnail_container: FrameLayout - private lateinit var activity_clingo_video_call: RelativeLayout - 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 isRecording: Boolean = true - - 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() - -// val params: ViewGroup.LayoutParams = dialog!!.window!!.attributes -// params.width = WindowManager.LayoutParams.MATCH_PARENT -// params.height = WindowManager.LayoutParams.MATCH_PARENT -// dialog!!.window!!.attributes = params as WindowManager.LayoutParams - - dialog?.window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) -// val parentLayoutParam: FrameLayout.LayoutParams = /*parentView.layoutParams as*/ FrameLayout.LayoutParams( -// LinearLayout.LayoutParams.MATCH_PARENT, -// LinearLayout.LayoutParams.MATCH_PARENT -// ) -// parentView.layoutParams = parentLayoutParam - } - - override fun getTheme(): Int { - return R.style.dialogTheme - } - - @SuppressLint("UseRequireInsteadOfGet") - override fun onCreateDialog(@Nullable savedInstanceState: Bundle?): Dialog {// FullScreenVideoTheme - val layoutInflater = requireActivity().layoutInflater - this.parentView = onCreateView(layoutInflater, null) - - val alertDialogBuilder: AlertDialog.Builder = - AlertDialog.Builder(requireContext(), R.style.dialogTheme) -// .setTitle(android.R.string.select_a_color) - .setView(this.parentView) -// .setPositiveButton(android.R.string.ok, { dialogInterface, i -> }) - alertDialogBuilder.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 alertDialogBuilder.create() -/* - - val dialog: Dialog = super.onCreateDialog(savedInstanceState) - // 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 - } - - private fun onCreateView( - inflater: LayoutInflater, container: ViewGroup? - ): View { - val view = inflater.inflate(R.layout.activity_video_call, container, false) - -// val parentViewLayoutParam: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams( -// ConstraintLayout.LayoutParams.MATCH_PARENT, -// ConstraintLayout.LayoutParams.MATCH_PARENT -// ) -// parentView.layoutParams = parentViewLayoutParam - // 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") - if (sessionStatusModel != null) - isRecording = sessionStatusModel!!.isRecording - } - initUI(view) - requestPermissions() - - handleDragDialog() - mDetector = GestureDetectorCompat( - requireContext(), - MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }) - ) - - return view - } - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return this.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) - recordContainer = view.findViewById(R.id.record_container) - activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) - - 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 - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - -// cmTimer = view.findViewById(R.id.cmTimer) - cmTimer.format = "mm:ss" - cmTimer.onChronometerTickListener = - Chronometer.OnChronometerTickListener { arg0: Chronometer? -> -// val f: NumberFormat = DecimalFormat("00") -// f.format(minutes) - 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 - } - val format = "%1$02d:%2$02d" // two digits - - arg0?.text = String.format(format, minutes, seconds) - Log.d(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() - handleVideoViewHeight(true) - - - - 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) -// } +//package com.hmg.hmgDr.ui.fragment // -// 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) +//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.appcompat.app.AlertDialog +//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.opentok.DynamicVideoRenderer +//import com.hmg.hmgDr.util.ViewsUtil +//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 // -// mSession!!.setReconnectionListener(object :Session.ReconnectionListener{ -// override fun onReconnecting(p0: Session?) { +//// check this if it works to solve keyboard not work when dialog is opened +//// https://stackoverflow.com/questions/55066977/how-to-prevent-custom-dialogfragment-from-hiding-keyboard-when-being-shown +//class VideoCallFragment : DialogFragment(), Session.SessionListener, +// PublisherListener, +// SubscriberKit.VideoListener, VideoCallView { // -// } -// -// override fun onReconnected(session: Session?) { -// session?.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?) { - Log.d(VideoCallFragment.TAG, "onVideoDisabled: Error ($s)") - -// 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.remoteBackground)) -// } - } - - override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(VideoCallFragment.TAG, "onVideoEnabled: Error ($s)") - -// if (mSubscriber != null) { -// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) -// } - } - - 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 - ) - ) -// if(isDismiss) -// dialog?.dismiss() -// else - onCallChangeCallStatusSuccessful() - } - - fun onCallChangeCallStatusSuccessful(){ - val returnIntent = Intent() - returnIntent.putExtra("CallEnd", sessionStatusModel) - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) - 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.remoteBackground - ) - ) - } - } - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - - handleVideoViewHeight(isFullScreen) - } - - private fun onMinimizedClicked(view: View?) { - if (isFullScreen) { - dialog?.window?.setLayout( - 400, - 600 - ) - recordContainer.visibility = View.GONE - } else { - dialog?.window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - } - isFullScreen = !isFullScreen - - val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand - btnMinimize.setImageResource(res) - setViewsVisibility() - -// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) - } - - private fun setViewsVisibility() { - val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = - btnMinimize.layoutParams as ConstraintLayout.LayoutParams - val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = - mCallBtn.layoutParams as ConstraintLayout.LayoutParams - - val iconSize: Int = requireContext().resources.getDimension(R.dimen.video_icon_size).toInt() - val iconSizeSmall: Int = - requireContext().resources.getDimension(R.dimen.video_icon_size_small).toInt() - - val localPreviewMargin: Int = - requireContext().resources.getDimension(R.dimen.local_preview_margin_top).toInt() - val localPreviewWidth: Int = - requireContext().resources.getDimension(R.dimen.local_preview_width).toInt() - val localPreviewHeight: Int = - requireContext().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 = - requireContext().resources.getDimension(R.dimen.remote_back_icon_size).toInt() - val remotePreviewIconSizeSmall: Int = - requireContext().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) - if (mPublisher != null && mPublisher!!.view.parent == null) { - mPublisherViewContainer.addView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.VISIBLE - -// 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) - - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.GONE -// 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 - - handleVideoViewHeight(isFullScreen) - } - - private fun handleVideoViewHeight(isFullScreen: Boolean) { - val layoutNameParam: ConstraintLayout.LayoutParams = - layoutName.layoutParams as ConstraintLayout.LayoutParams - val layoutMiniParam: ConstraintLayout.LayoutParams = - layoutMini.layoutParams as ConstraintLayout.LayoutParams - val controlPanelParam: ConstraintLayout.LayoutParams = - controlPanel.layoutParams as ConstraintLayout.LayoutParams - - val layoutNameHeight: Int = - requireContext().resources.getDimension(R.dimen.layout_name_height).toInt() - val layoutMiniHeight: Int = - requireContext().resources.getDimension(R.dimen.layout_mini_height).toInt() - val panelHeight: Int = requireContext().resources.getDimension(R.dimen.layout_panel_height).toInt() - val panelHeightSmall: Int = - requireContext().resources.getDimension(R.dimen.layout_panel_height_small).toInt() - - val panelPadding: Int = - requireContext().resources.getDimension(R.dimen.padding_space_big).toInt() - val panelPaddingMedium: Int = - requireContext().resources.getDimension(R.dimen.padding_space_medium).toInt() - - val temp = getStatusBarHeight() / 2 - - val screenWidth: Float - val screenHeight: Float - - if (isFullScreen) { - screenWidth = ViewsUtil.getWidthDp(requireContext()) - screenHeight = ViewsUtil.getHeightDp(requireContext()) - - layoutNameParam.height = layoutNameHeight + temp - layoutMiniParam.height = 0 - controlPanelParam.height = panelHeight + temp - - controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) - } else { - - if (isCircle) { - screenWidth = 300F - screenHeight = 300F - - layoutNameParam.height = 0 - layoutMiniParam.height = 0 - controlPanelParam.height = 0 - } else { - screenWidth = 400F - screenHeight = 600F - - layoutNameParam.height = 0 - layoutMiniParam.height = layoutMiniHeight - controlPanelParam.height = panelHeightSmall - } - - controlPanel.setPadding( - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium - ) - } - - layoutName.layoutParams = layoutNameParam - layoutMini.layoutParams = layoutMiniParam - controlPanel.layoutParams = controlPanelParam - - var videoStreamHeight = - screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height - - if (isFullScreen) { -// videoStreamHeight -= getStatusBarHeight() / 2 - } - - val callLayoutParam: ConstraintLayout.LayoutParams = - activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams - - callLayoutParam.height = videoStreamHeight.toInt() - callLayoutParam.width = screenWidth.toInt() - } - - 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) - -// if (!isCameraClicked) { -// 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)) -// } - } - } - - 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 +//// 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 recordContainer: FrameLayout +//// private lateinit var thumbnail_container: FrameLayout +//// private lateinit var activity_clingo_video_call: RelativeLayout +//// 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 isRecording: Boolean = true +//// +//// 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() +//// +////// val params: ViewGroup.LayoutParams = dialog!!.window!!.attributes +////// params.width = WindowManager.LayoutParams.MATCH_PARENT +////// params.height = WindowManager.LayoutParams.MATCH_PARENT +////// dialog!!.window!!.attributes = params as WindowManager.LayoutParams +//// +//// dialog?.window?.setLayout( +//// LinearLayout.LayoutParams.MATCH_PARENT, +//// LinearLayout.LayoutParams.MATCH_PARENT +//// ) +////// val parentLayoutParam: FrameLayout.LayoutParams = /*parentView.layoutParams as*/ FrameLayout.LayoutParams( +////// LinearLayout.LayoutParams.MATCH_PARENT, +////// LinearLayout.LayoutParams.MATCH_PARENT +////// ) +////// parentView.layoutParams = parentLayoutParam +//// } +//// +//// override fun getTheme(): Int { +//// return R.style.dialogTheme +//// } +//// +//// @SuppressLint("UseRequireInsteadOfGet") +//// override fun onCreateDialog(@Nullable savedInstanceState: Bundle?): Dialog {// FullScreenVideoTheme +//// val layoutInflater = requireActivity().layoutInflater +//// this.parentView = onCreateView(layoutInflater, null) +//// +//// val alertDialogBuilder: AlertDialog.Builder = +//// AlertDialog.Builder(requireContext(), R.style.dialogTheme) +////// .setTitle(android.R.string.select_a_color) +//// .setView(this.parentView) +////// .setPositiveButton(android.R.string.ok, { dialogInterface, i -> }) +//// alertDialogBuilder.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 alertDialogBuilder.create() +/////* +//// +//// val dialog: Dialog = super.onCreateDialog(savedInstanceState) +//// // 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 +//// } +//// +//// private fun onCreateView( +//// inflater: LayoutInflater, container: ViewGroup? +//// ): View { +//// val view = inflater.inflate(R.layout.activity_video_call, container, false) +//// +////// val parentViewLayoutParam: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams( +////// ConstraintLayout.LayoutParams.MATCH_PARENT, +////// ConstraintLayout.LayoutParams.MATCH_PARENT +////// ) +////// parentView.layoutParams = parentViewLayoutParam +//// // 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") +//// if (sessionStatusModel != null) +//// isRecording = sessionStatusModel!!.isRecording +//// } +//// initUI(view) +//// requestPermissions() +//// +//// handleDragDialog() +//// mDetector = GestureDetectorCompat( +//// requireContext(), +//// MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }) +//// ) +//// +//// return view +//// } +//// +//// override fun onCreateView( +//// inflater: LayoutInflater, container: ViewGroup?, +//// savedInstanceState: Bundle? +//// ): View { +//// return this.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) +//// recordContainer = view.findViewById(R.id.record_container) +//// activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) +//// +//// 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 +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// +////// cmTimer = view.findViewById(R.id.cmTimer) +//// cmTimer.format = "mm:ss" +//// cmTimer.onChronometerTickListener = +//// Chronometer.OnChronometerTickListener { arg0: Chronometer? -> +////// val f: NumberFormat = DecimalFormat("00") +////// f.format(minutes) +//// 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 +//// } +//// val format = "%1$02d:%2$02d" // two digits +//// +//// arg0?.text = String.format(format, minutes, seconds) +//// Log.d(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() +//// handleVideoViewHeight(true) +//// +//// +//// +//// 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) +////// +////// mSession!!.setReconnectionListener(object :Session.ReconnectionListener{ +////// override fun onReconnecting(p0: Session?) { +////// +////// } +////// +////// override fun onReconnected(session: Session?) { +////// session?.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?) { +//// Log.d(VideoCallFragment.TAG, "onVideoDisabled: Error ($s)") +//// +////// 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.remoteBackground)) +////// } +//// } +//// +//// override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(VideoCallFragment.TAG, "onVideoEnabled: Error ($s)") +//// +////// if (mSubscriber != null) { +////// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +////// } +//// } +//// +//// 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 +//// ) +//// ) +////// if(isDismiss) +////// dialog?.dismiss() +////// else +//// onCallChangeCallStatusSuccessful() +//// } +//// +//// fun onCallChangeCallStatusSuccessful(){ +//// val returnIntent = Intent() +//// returnIntent.putExtra("CallEnd", sessionStatusModel) +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) +//// 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.remoteBackground +//// ) +//// ) +//// } +//// } +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// +//// handleVideoViewHeight(isFullScreen) +//// } +//// +//// private fun onMinimizedClicked(view: View?) { +//// if (isFullScreen) { +//// dialog?.window?.setLayout( +//// 400, +//// 600 +//// ) +//// recordContainer.visibility = View.GONE +//// } else { +//// dialog?.window?.setLayout( +//// LinearLayout.LayoutParams.MATCH_PARENT, +//// LinearLayout.LayoutParams.MATCH_PARENT +//// ) +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// } +//// isFullScreen = !isFullScreen +//// +//// val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand +//// btnMinimize.setImageResource(res) +//// setViewsVisibility() +//// +////// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) +//// } +//// +//// private fun setViewsVisibility() { +//// val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = +//// btnMinimize.layoutParams as ConstraintLayout.LayoutParams +//// val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = +//// mCallBtn.layoutParams as ConstraintLayout.LayoutParams +//// +//// val iconSize: Int = requireContext().resources.getDimension(R.dimen.video_icon_size).toInt() +//// val iconSizeSmall: Int = +//// requireContext().resources.getDimension(R.dimen.video_icon_size_small).toInt() +//// +//// val localPreviewMargin: Int = +//// requireContext().resources.getDimension(R.dimen.local_preview_margin_top).toInt() +//// val localPreviewWidth: Int = +//// requireContext().resources.getDimension(R.dimen.local_preview_width).toInt() +//// val localPreviewHeight: Int = +//// requireContext().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 = +//// requireContext().resources.getDimension(R.dimen.remote_back_icon_size).toInt() +//// val remotePreviewIconSizeSmall: Int = +//// requireContext().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) +//// if (mPublisher != null && mPublisher!!.view.parent == null) { +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.VISIBLE +//// +////// 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) +//// +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.GONE +////// 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 +//// +//// handleVideoViewHeight(isFullScreen) +//// } +//// +//// private fun handleVideoViewHeight(isFullScreen: Boolean) { +//// val layoutNameParam: ConstraintLayout.LayoutParams = +//// layoutName.layoutParams as ConstraintLayout.LayoutParams +//// val layoutMiniParam: ConstraintLayout.LayoutParams = +//// layoutMini.layoutParams as ConstraintLayout.LayoutParams +//// val controlPanelParam: ConstraintLayout.LayoutParams = +//// controlPanel.layoutParams as ConstraintLayout.LayoutParams +//// +//// val layoutNameHeight: Int = +//// requireContext().resources.getDimension(R.dimen.layout_name_height).toInt() +//// val layoutMiniHeight: Int = +//// requireContext().resources.getDimension(R.dimen.layout_mini_height).toInt() +//// val panelHeight: Int = requireContext().resources.getDimension(R.dimen.layout_panel_height).toInt() +//// val panelHeightSmall: Int = +//// requireContext().resources.getDimension(R.dimen.layout_panel_height_small).toInt() +//// +//// val panelPadding: Int = +//// requireContext().resources.getDimension(R.dimen.padding_space_big).toInt() +//// val panelPaddingMedium: Int = +//// requireContext().resources.getDimension(R.dimen.padding_space_medium).toInt() +//// +//// val temp = getStatusBarHeight() / 2 +//// +//// val screenWidth: Float +//// val screenHeight: Float +//// +//// if (isFullScreen) { +//// screenWidth = ViewsUtil.getWidthDp(requireContext()) +//// screenHeight = ViewsUtil.getHeightDp(requireContext()) +//// +//// layoutNameParam.height = layoutNameHeight + temp +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = panelHeight + temp +//// +//// controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) +//// } else { +//// +//// if (isCircle) { +//// screenWidth = 300F +//// screenHeight = 300F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = 0 +//// } else { +//// screenWidth = 400F +//// screenHeight = 600F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = layoutMiniHeight +//// controlPanelParam.height = panelHeightSmall +//// } +//// +//// controlPanel.setPadding( +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium +//// ) +//// } +//// +//// layoutName.layoutParams = layoutNameParam +//// layoutMini.layoutParams = layoutMiniParam +//// controlPanel.layoutParams = controlPanelParam +//// +//// var videoStreamHeight = +//// screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height +//// +//// if (isFullScreen) { +////// videoStreamHeight -= getStatusBarHeight() / 2 +//// } +//// +//// val callLayoutParam: ConstraintLayout.LayoutParams = +//// activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams +//// +//// callLayoutParam.height = videoStreamHeight.toInt() +//// callLayoutParam.width = screenWidth.toInt() +//// } +//// +//// 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) +//// +////// if (!isCameraClicked) { +////// 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)) +////// } +//// } +//// } +//// +//// 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/opentok/DynamicVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt index 818b231a..6184bde2 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt @@ -1,379 +1,379 @@ -package com.hmg.hmgDr.util.opentok - -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 +//package com.hmg.hmgDr.util.opentok +// +//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/opentok/ThumbnailCircleVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt index 26630bea..4438f01e 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt @@ -1,357 +1,357 @@ -package com.hmg.hmgDr.util.opentok - -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 - } -} +//package com.hmg.hmgDr.util.opentok +// +//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/build.gradle b/android/build.gradle index c62d79a6..34cc897e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -15,7 +15,7 @@ allprojects { repositories { google() - jcenter() +// jcenter() mavenCentral() maven { url 'https://developer.huawei.com/repo/' } // maven { url 'https://tokbox.bintray.com/maven' } @@ -46,6 +46,7 @@ subprojects { if (namespace == null) { namespace project.group } + project.android.compileSdkVersion 37 } } } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 8f3239ab..a97e89ca 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 51fac1d1..053f5800 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,8 +18,8 @@ pluginManagement { plugins { id 'dev.flutter.flutter-plugin-loader' version "1.0.0" // apply true - id "org.jetbrains.kotlin.android" version "2.1.0" apply false - id 'com.android.application' version "8.9.0" apply false + id "com.android.application" version '9.0.1' apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false id "com.google.gms.google-services" version "4.4.0" apply false } diff --git a/ios/Podfile b/ios/Podfile index 35a4aab3..c583ec2f 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project - platform :ios, '13.0' + platform :ios, '15.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 27f7bfa6..ac64dc31 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ @@ -198,7 +198,6 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, CD1E4AEFF4CC6FD150483363 /* [CP] Embed Pods Frameworks */, - 6BD71B7017878A134266DEFC /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -238,7 +237,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -303,24 +302,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 6BD71B7017878A134266DEFC /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/permission_handler_apple/permission_handler_apple_privacy.bundle", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/permission_handler_apple_privacy.bundle", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -347,30 +328,13 @@ "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseInstallations/FirebaseInstallations.framework", - "${BUILT_PRODUCTS_DIR}/FirebaseMessaging/FirebaseMessaging.framework", - "${BUILT_PRODUCTS_DIR}/GoogleDataTransport/GoogleDataTransport.framework", - "${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework", - "${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework", - "${BUILT_PRODUCTS_DIR}/OrderedSet/OrderedSet.framework", - "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework", "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", - "${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework", "${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework", - "${BUILT_PRODUCTS_DIR}/Try/Try.framework", - "${BUILT_PRODUCTS_DIR}/barcode_scan2/barcode_scan2.framework", - "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", - "${BUILT_PRODUCTS_DIR}/flutter_inappwebview_ios/flutter_inappwebview_ios.framework", - "${BUILT_PRODUCTS_DIR}/flutter_keyboard_visibility/flutter_keyboard_visibility.framework", - "${BUILT_PRODUCTS_DIR}/fluttertoast/fluttertoast.framework", - "${BUILT_PRODUCTS_DIR}/local_auth_ios/local_auth_ios.framework", "${BUILT_PRODUCTS_DIR}/maps_launcher/maps_launcher.framework", - "${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework", - "${BUILT_PRODUCTS_DIR}/path_provider_foundation/path_provider_foundation.framework", - "${BUILT_PRODUCTS_DIR}/speech_to_text/speech_to_text.framework", + "${BUILT_PRODUCTS_DIR}/open_filex/open_filex.framework", "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/CptShare/CptShare.framework/CptShare", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/Whiteboard/Whiteboard.framework/Whiteboard", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/ZoomTask/ZoomTask.framework/ZoomTask", "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/ZoomVideoSDK/ZoomVideoSDK.framework/ZoomVideoSDK", "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/zm_annoter_dynamic/zm_annoter_dynamic.framework/zm_annoter_dynamic", "${PODS_XCFRAMEWORKS_BUILD_DIR}/ZoomVideoSDK/zoomcml/zoomcml.framework/zoomcml", @@ -381,30 +345,13 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseInstallations.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseMessaging.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleDataTransport.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OrderedSet.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Try.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan2.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_inappwebview_ios.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_keyboard_visibility.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fluttertoast.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/local_auth_ios.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/maps_launcher.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider_foundation.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/speech_to_text.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/open_filex.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CptShare.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Whiteboard.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZoomTask.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ZoomVideoSDK.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/zm_annoter_dynamic.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/zoomcml.framework", @@ -497,7 +444,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -522,7 +469,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -590,7 +537,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -641,7 +588,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -668,7 +615,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -704,7 +651,7 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -749,7 +696,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index e577bcf4..3e43a1b2 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -5,7 +5,7 @@ import OpenTok // Copyright © 2020 Cloud. All rights reserved. @main -@objc class AppDelegate: FlutterAppDelegate ,ICallProtocol { +@objc class AppDelegate: FlutterAppDelegate ,ICallProtocol , FlutterImplicitEngineDelegate { var result: FlutterResult? @@ -23,9 +23,12 @@ import OpenTok didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - GeneratedPluginRegistrant.register(with: self) +// GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index d818fbb3..a72adc37 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -48,6 +48,27 @@ Need to upload image NSSpeechRecognitionUsageDescription This permission is not needed by the app, but it is required by an underlying API. If you see this dialog, contact us. + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + UIApplicationSupportsIndirectInputEvents UIBackgroundModes diff --git a/lib/client/base_app_client.dart b/lib/client/base_app_client.dart index bf0085d0..ef0b88b8 100755 --- a/lib/client/base_app_client.dart +++ b/lib/client/base_app_client.dart @@ -145,7 +145,6 @@ class BaseAppClient { printer: PrettyPrinter( methodCount: 2, errorMethodCount: 5, - lineLength: 1000, colors: true, printEmojis: true, ), diff --git a/lib/config/config.dart b/lib/config/config.dart index 2621fbc6..86737dca 100755 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -385,7 +385,7 @@ const IS_INFECTIOUS_DISEASE_PENDING = 'Services/DoctorApplication.svc/REST/IsInt const INFECTIOUS_HISTORY = 'Services/DoctorApplication.svc/REST/InterventionHistory'; const UPDATE_INFECTIOUS_STATUS = 'Services/DoctorApplication.svc/REST/UpdateInterventionStatus'; const GET_NURSING_STATIONS = 'Services/DoctorApplication.svc/REST/GetWards'; -const GET_ATTACHMENT = 'Services/Patients.svc/REST/GetVidaLabResultAttachment'; +const GET_ATTACHMENT = 'Services/DataStreaming.svc/REST/GetVidaLabResultAttachment'; var selectedPatientType = 1; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 9a0baa84..7c2aedd6 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1291,8 +1291,8 @@ const Map> localizedValues = { "ar":"لا يوجد تشخيص سابق" }, "showAttachment":{ - "en":"Show\nAttachment", - "ar":"عرض\nالمرفقات" + "en":"Show Attachment", + "ar":"عرض المرفقات" }, "selectAnAttachment":{ "en":"Select An Attachment", diff --git a/lib/core/model/auth/activation_Code_req_model.dart b/lib/core/model/auth/activation_Code_req_model.dart index 0603360e..9e68ecfe 100644 --- a/lib/core/model/auth/activation_Code_req_model.dart +++ b/lib/core/model/auth/activation_Code_req_model.dart @@ -39,6 +39,8 @@ class ActivationCodeModel { data['OTP_SendType'] = otpSendType; data['generalid'] = this.generalid; data['LoginDoctorID'] = this.loginDoctorID; + data['NotificationCenterAppGUID'] = "QmNYN21MNHBTM2tkdjU2ZzdBOUhSdWlwT21h"; + data['NotificationCenterAppSeviceGUID'] = "d8bd5c76-4b50-4122-81d0-c3aa25db08a2"; return data; } } diff --git a/lib/core/model/labs/all_special_lab_result_model.dart b/lib/core/model/labs/all_special_lab_result_model.dart index ad78cd4d..e3315e31 100644 --- a/lib/core/model/labs/all_special_lab_result_model.dart +++ b/lib/core/model/labs/all_special_lab_result_model.dart @@ -58,6 +58,8 @@ class AllSpecialLabResultModel { bool? IsLabTestAttachment; // for the attachment icon in the lab result list dynamic LabAccessionNo; dynamic FileHash; + dynamic testDescription; + dynamic testShortDescription; AllSpecialLabResultModel( {this.actualDoctorRate, @@ -110,7 +112,10 @@ class AllSpecialLabResultModel { //this.speciality, this.status, this.statusDesc, - this.strOrderDate}); + this.strOrderDate, + this.testShortDescription, + this.testDescription, + }); AllSpecialLabResultModel.fromJson(Map json) { actualDoctorRate = json['ActualDoctorRate']; @@ -167,6 +172,8 @@ class AllSpecialLabResultModel { IsLabTestAttachment = json['IsLabTestAttachment'] ?? false; LabAccessionNo = json['LabAccessionNo'] ?? json['AccessionNo']; + testDescription = json['Description'] ; + testShortDescription = json['TestShortDescription']; if (json['FileNameWithExtensionList'] != null) { FileNameWithExtensionList = []; diff --git a/lib/core/model/labs/lab_result.dart b/lib/core/model/labs/lab_result.dart index 75040ccb..3026f870 100644 --- a/lib/core/model/labs/lab_result.dart +++ b/lib/core/model/labs/lab_result.dart @@ -21,10 +21,15 @@ class LabResult { String? verifiedOn; dynamic verifiedOnDateTime; bool? IsLabTestAttachment; // for the attachment icon in the lab result list + bool? IsPackage; // for the attachment icon in the lab result list dynamic LabAccessionNo; List? FileNameWithExtensionList; dynamic FileHash; List? UploadedDocuments; + String? packageName = ""; + String? TestShortDescription = ""; + String? PackageShortDescription = ""; + LabResult( {this.description, @@ -52,6 +57,8 @@ class LabResult { this.LabAccessionNo, this.FileNameWithExtensionList, this.FileHash, + this.TestShortDescription, + this.PackageShortDescription, this.UploadedDocuments}); LabResult.fromJson(Map json) { @@ -77,8 +84,12 @@ class LabResult { verifiedOn = json['VerifiedOn']; verifiedOnDateTime = json['VerifiedOnDateTime']; IsLabTestAttachment = json['IsLabTestAttachment'] ?? false; + IsPackage = json['IsPackage'] ?? false; LabAccessionNo = json['LabAccessionNo'] ?? json['AccessionNo']; + packageName = json['PackageName'] ??null ; + TestShortDescription = json['TestShortDescription'] ??null ; + PackageShortDescription = json['PackageShortDescription'] ??null ; if (json['FileNameWithExtensionList'] != null) { FileNameWithExtensionList = []; diff --git a/lib/core/model/labs/patient_lab_special_result.dart b/lib/core/model/labs/patient_lab_special_result.dart index 809f26b7..5b96a143 100644 --- a/lib/core/model/labs/patient_lab_special_result.dart +++ b/lib/core/model/labs/patient_lab_special_result.dart @@ -12,6 +12,10 @@ class PatientLabSpecialResult { List? UploadedDocuments; bool? IsLabTestAttachment; // for the attachment icon in the lab result list dynamic LabAccessionNo; + String? testCode; + String? testDescription; + String? testID; + String? testShortDescription; PatientLabSpecialResult( {this.invoiceNo, @@ -21,7 +25,12 @@ class PatientLabSpecialResult { this.resultDataTxt, this.FileNameWithExtensionList, this.UploadedDocuments, - this.IsLabTestAttachment}); + this.IsLabTestAttachment, + this.testCode, + this.testDescription, + this.testShortDescription, + this.testID, + }); PatientLabSpecialResult.fromJson(Map json) { SetupID = json['SetupID']; @@ -46,6 +55,11 @@ class PatientLabSpecialResult { } IsLabTestAttachment = json['IsLabTestAttachment'] ?? false; + + testCode = json['TestCode']; + testDescription = json['Description']; + testID = json['TestID']; + testShortDescription = json['TestShortDescription']; } Map toJson() { diff --git a/lib/core/service/patient_medical_file/lab_order/labs_service.dart b/lib/core/service/patient_medical_file/lab_order/labs_service.dart index 62f7174c..451a6bfb 100644 --- a/lib/core/service/patient_medical_file/lab_order/labs_service.dart +++ b/lib/core/service/patient_medical_file/lab_order/labs_service.dart @@ -60,6 +60,7 @@ class LabsService extends BaseService { List patientLabSpecialResult = []; List labResultList = []; + Map> mappedLabResultList = {}; List labOrdersResultsList = []; List labAttachment = []; List labOrdersResultHistoryList = []; @@ -125,11 +126,48 @@ class LabsService extends BaseService { labResultList.add(LabResult.fromJson(lab)); }); } + + ///sorting the list based on the package name or test code right now if the vida3 add the package name for the doctor application endpoint then it will work cause the elements are going to give the priority to the package name if it is not null or empty otherwise it will give the priority to the test code and then it will sort the list based on the package name first then goes for the test code to sort and enjoy + mappedLabResultList = groupLabResultsByPackageName(labResultList); }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: body); } + Map> groupLabResultsByPackageName(List labResults) { + Map> groupedResults = {}; + + // Group results by package name + for (var labResult in labResults) { + String packageName = labResult.packageName?? labResult.testCode ?? 'Unknown Package'; + + if (groupedResults.containsKey(packageName)) { + // Package name exists, add to existing list + groupedResults[packageName]!.add(labResult); + } else { + // Package name doesn't exist, create new key with new list + groupedResults[packageName] = [labResult]; + } + } + + // Sort each list alphabetically by description + groupedResults.forEach((key, list) { + list.sort((a, b) { + String descA = (a.description ?? '').toLowerCase(); + String descB = (b.description ?? '').toLowerCase(); + return descA.compareTo(descB); + }); + }); + + // Sort the map keys alphabetically and return a new sorted map + var sortedKeys = groupedResults.keys.toList()..sort((a, b) => a.toLowerCase().compareTo(b.toLowerCase())); + Map> sortedGroupedResults = {}; + for (var key in sortedKeys) { + sortedGroupedResults[key] = groupedResults[key]!; + } + + return sortedGroupedResults; + } Future getPatientLabOrdersResults({PatientLabOrders? patientLabOrder, required String procedure, required PatiantInformtion patient}) async { hasError = false; diff --git a/lib/core/viewModel/PatientSearchViewModel.dart b/lib/core/viewModel/PatientSearchViewModel.dart index 0656f73f..d91e34dc 100644 --- a/lib/core/viewModel/PatientSearchViewModel.dart +++ b/lib/core/viewModel/PatientSearchViewModel.dart @@ -104,7 +104,7 @@ class PatientSearchViewModel extends BaseViewModel { String dateTo; String dateFrom; if (OutPatientFilterType.Previous == outPatientFilterType) { - selectedFromDate = DateTime(DateTime.now().year, DateTime.now().month - 1, DateTime.now().day); + selectedFromDate = DateTime(DateTime.now().year, DateTime.now().month , DateTime.now().day-2); selectedToDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day - 1); dateTo = AppDateUtils.convertDateToFormat(selectedToDate!, 'yyyy-MM-dd'); dateFrom = AppDateUtils.convertDateToFormat(selectedFromDate!, 'yyyy-MM-dd'); diff --git a/lib/core/viewModel/authentication_view_model.dart b/lib/core/viewModel/authentication_view_model.dart index 4622be77..9129a285 100755 --- a/lib/core/viewModel/authentication_view_model.dart +++ b/lib/core/viewModel/authentication_view_model.dart @@ -1,5 +1,5 @@ import 'dart:io'; - +import 'package:local_auth_darwin/local_auth_darwin.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/view_state.dart'; @@ -30,7 +30,6 @@ import 'package:flutter/services.dart'; // import 'package:huawei_hmsavailability/huawei_hmsavailability.dart'; // import 'package:local_auth/auth_strings.dart'; import 'package:local_auth/local_auth.dart'; -import 'package:local_auth_ios/local_auth_ios.dart'; enum APP_STATUS { LOADING, UNAUTHENTICATED, AUTHENTICATED, UNVERIFIED } @@ -279,15 +278,12 @@ class AuthenticationViewModel extends BaseViewModel { /// ask user to add his biometric showIOSAuthMessages() async { - const iosStrings = IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please Enable Your Touch ID'); + final iosStrings = IOSAuthMessages(cancelButton: 'cancel', ); try { await auth.authenticate( localizedReason: 'Scan your fingerprint to authenticate', authMessages: [iosStrings], - options: AuthenticationOptions( - useErrorDialogs: true, - stickyAuth: true, - ), + ); } on PlatformException catch (e) { DrAppToastMsg.showErrorToast(e.toString()); diff --git a/lib/core/viewModel/labs_view_model.dart b/lib/core/viewModel/labs_view_model.dart index 13c70d5e..6bd856bd 100644 --- a/lib/core/viewModel/labs_view_model.dart +++ b/lib/core/viewModel/labs_view_model.dart @@ -74,6 +74,7 @@ class LabsViewModel extends BaseViewModel { List get patientLabSpecialResult => _labsService.patientLabSpecialResult; List get labResultList => _labsService.labResultList; + Map> get mappedLabResultList => _labsService.mappedLabResultList; List labResultLists = []; diff --git a/lib/main.dart b/lib/main.dart index ab1c9b6a..54e571b1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -18,6 +18,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_quill/flutter_quill.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:timezone/data/latest_all.dart' as tz; @@ -86,6 +87,7 @@ class MyApp extends StatelessWidget { locale: projectProvider.appLocal, localizationsDelegates: [ TranslationBaseDelegate(), + FlutterQuillLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, diff --git a/lib/screens/patients/In_patient/list_of_my_inpatient.dart b/lib/screens/patients/In_patient/list_of_my_inpatient.dart index fe861da4..85cef378 100644 --- a/lib/screens/patients/In_patient/list_of_my_inpatient.dart +++ b/lib/screens/patients/In_patient/list_of_my_inpatient.dart @@ -26,8 +26,10 @@ class ListOfMyInpatient extends StatelessWidget { margin: EdgeInsets.symmetric(horizontal: 16.0), child: patientSearchViewModel.filteredMyInPatientItems.length == 0 ? NoData() - : NotificationListener( - child: ListView.builder( + : + NotificationListener( + child: + ListView.builder( itemCount: patientSearchViewModel.filteredMyInPatientItems.length, scrollDirection: Axis.vertical, diff --git a/lib/screens/patients/profile/diabetic_chart/line_chart_for_diabetic.dart b/lib/screens/patients/profile/diabetic_chart/line_chart_for_diabetic.dart index c1501cfa..40336f3d 100644 --- a/lib/screens/patients/profile/diabetic_chart/line_chart_for_diabetic.dart +++ b/lib/screens/patients/profile/diabetic_chart/line_chart_for_diabetic.dart @@ -80,7 +80,7 @@ class LineChartForDiabetic extends StatelessWidget { return LineChartData( lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( - tooltipBgColor: Colors.white, + getTooltipColor: (LineBarSpot touchedSpot) => Colors.white, ), touchCallback: (FlTouchEvent event, LineTouchResponse? touchResponse) {}, handleBuiltInTouches: true, diff --git a/lib/screens/patients/profile/lab_result/history/line_chart_curved_lab_history.dart b/lib/screens/patients/profile/lab_result/history/line_chart_curved_lab_history.dart index d2c4e4f3..7ea1d1d8 100644 --- a/lib/screens/patients/profile/lab_result/history/line_chart_curved_lab_history.dart +++ b/lib/screens/patients/profile/lab_result/history/line_chart_curved_lab_history.dart @@ -86,7 +86,7 @@ class LineChartCurvedLabHistoryState extends State { return LineChartData( lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( - tooltipBgColor: Colors.white, + getTooltipColor: (LineBarSpot touchedSpot) => Colors.white, ), touchCallback: (event, touchResponse) {}, handleBuiltInTouches: true, diff --git a/lib/screens/patients/profile/lab_result/laboratory_result/lab_result_widget.dart b/lib/screens/patients/profile/lab_result/laboratory_result/lab_result_widget.dart index b22be730..b590c8a5 100644 --- a/lib/screens/patients/profile/lab_result/laboratory_result/lab_result_widget.dart +++ b/lib/screens/patients/profile/lab_result/laboratory_result/lab_result_widget.dart @@ -6,12 +6,10 @@ import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart'; import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/screens/patients/profile/lab_result/laboratory_result/flow_chart_page.dart'; import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; -import 'package:doctor_app_flutter/utils/utils.dart'; import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:open_filex/open_filex.dart'; import 'package:provider/provider.dart'; class LabResultWidget extends StatelessWidget { @@ -24,15 +22,16 @@ class LabResultWidget extends StatelessWidget { LabResultWidget({Key? key, required this.filterName, required this.patientLabResultList, required this.patientLabOrder, required this.patient, required this.isInpatient, required this.model}) : super(key: key); - late ProjectViewModel projectViewModel; @override Widget build(BuildContext context) { - projectViewModel = Provider.of(context); + Provider.of(context); return Container( width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: 8), child: Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // if (!isInpatient) @@ -41,234 +40,246 @@ class LabResultWidget extends StatelessWidget { children: [ Row( children: [ - AppText( - filterName, - fontSize: SizeConfig.textMultiplier! * 2.0, - fontWeight: FontWeight.w700, - ), - ], - ), - ], - ), - SizedBox( - height: 8, - ), - Row( - children: [ - Expanded( - child: Container( - child: Center( + Visibility( + visible: filterName.isNotEmpty, child: AppText( - TranslationBase.of(context).description, - color: Colors.black, - fontSize: SizeConfig.textMultiplier! * 2.0, + filterName, + fontSize: SizeConfig.textMultiplier! * 1.6, fontWeight: FontWeight.w700, ), ), - ), - ), - Expanded( - child: Container( - child: Center( - child: AppText( - TranslationBase.of(context).value, - color: Colors.black, - fontSize: SizeConfig.textMultiplier! * 2.0, - fontWeight: FontWeight.w700, - ), - ), - ), - ), - Expanded( - child: Container( - child: Center( - child: AppText( - TranslationBase.of(context).range, - fontSize: SizeConfig.textMultiplier! * 2.0, - fontWeight: FontWeight.w700, - ), - ), - ), + ], ), - Expanded( - child: Container(), - ) ], ), - Divider( - color: Colors.grey.shade500, - thickness: 1, - ), SizedBox( - height: 12, + height: 16, ), ListView.builder( itemCount: patientLabResultList.length, scrollDirection: Axis.vertical, - physics: ScrollPhysics(), + physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, itemBuilder: (context, index) { return Column( + mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.rectangle, - color: Color(0X55F2F2F2), - borderRadius: BorderRadius.all( - Radius.circular(8.0), - ), - ), - child: Row( + SizedBox(height: 8,), + Visibility( + visible: index == 0, + child: Column( children: [ - Expanded( - child: Container( - padding: EdgeInsets.all(10), - child: Center( - child: AppText( - patientLabResultList[index].description!, - textAlign: TextAlign.center, - fontSize: SizeConfig.textMultiplier! * 1.8, - isCopyable: true, - ), - ), - ), - ), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - if (patientLabResultList[index].checkResultStatus() != 0) - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.red.shade700, - ), - child: Icon( - patientLabResultList[index].checkResultStatus() == 1 ? Icons.arrow_upward : Icons.arrow_downward, - color: Colors.white, - size: 16, - ), + Visibility( + visible: patientLabResultList[index].PackageShortDescription != null && patientLabResultList[index].PackageShortDescription?.isNotEmpty == true , + child:Column( + children: [ + AppText( + patientLabResultList[index].PackageShortDescription??"", + fontSize: SizeConfig.textMultiplier! * 1.3, + fontWeight: FontWeight.w400, + color: Colors.black87, + isCopyable: true, ), - Expanded( - child: Container( - alignment: Alignment.center, - padding: EdgeInsets.symmetric(vertical: 10, horizontal: 4), - child: Center( - child: AppText( - patientLabResultList[index].resultValue ?? "" + " " + "${patientLabResultList[index].uOM ?? ""}", - textAlign: TextAlign.center, - isCopyable: true, - fontSize: SizeConfig.textMultiplier! * 1.8, - ), - ), + SizedBox( + height: 8, ), - ), - ], - ), - ), - Expanded( - child: Container( - padding: EdgeInsets.all(10), - // color: Colors.white, - child: Center( - child: AppText( - patientLabResultList[index].referanceRange!, - textAlign: TextAlign.center, - fontSize: SizeConfig.textMultiplier! * 1.8, - isCopyable: true, - ), - ), - ), - ), - Expanded( - child: Column( - children: [ - Visibility( - visible: patientLabResultList[index].IsLabTestAttachment ?? false, - child: InkWell( - onTap: () async { - var labAccessNumber = patientLabResultList[index].LabAccessionNo; - // if (patientLabResultList[index].FileNameWithExtensionList?.isNotEmpty == true || patientLabResultList[index].FileNameWithExtensionList?.length == 1) { - // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: patientLabResultList[index].FileNameWithExtensionList?.first); - // model.openPDF(); - // return; - // } - // - // if (patientLabResultList[index].UploadedDocuments?.isNotEmpty == true || patientLabResultList[index].UploadedDocuments?.length == 1) { - // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: patientLabResultList[index].UploadedDocuments?.first); - // model.openPDF(); - // return; - // } - showUploadedDocumentsBottomSheet( - context, - documents: patientLabResultList[index].UploadedDocuments, - fileName: patientLabResultList[index].FileNameWithExtensionList, - labAccessNumber: labAccessNumber, - projectID: int.parse(patientLabResultList[index].projectID!), - setupID: patientLabResultList[index].setupID); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AppText( - TranslationBase.of(context).showAttachment, - textDecoration: TextDecoration.underline, - color: Colors.red.shade700, - fontSize: SizeConfig.textMultiplier! * 1.2, - fontWeight: FontWeight.w700, - ), - ], - ), + ], + ) ), + Visibility( + visible: (patientLabResultList.any((lab) => lab.IsLabTestAttachment ?? false)) && (patientLabResultList.any((lab) => lab.IsPackage ?? false)), + child: Center( + child: InkWell( + onTap: () async { + final labWithAttachment = patientLabResultList[index]; + var labAccessNumber = labWithAttachment.LabAccessionNo; + + showUploadedDocumentsBottomSheet( + context, + documents: labWithAttachment.UploadedDocuments, + fileName: labWithAttachment.FileNameWithExtensionList, + labAccessNumber: labAccessNumber, + projectID: int.parse(labWithAttachment.projectID!), + setupID: labWithAttachment.setupID, + ); + }, + child: Container( + width: double.infinity, + + padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(16), ), - ), - SizedBox( - height: 8, - ), - InkWell( - onTap: () { - Navigator.push( - context, - FadePage( - page: FlowChartPage( - filterName: patientLabResultList[index].description!, - patientLabOrder: patientLabOrder, - patient: patient, - isInpatient: isInpatient, - ), - ), - ); - }, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + Icon( + Icons.description_outlined, + color: Colors.red.shade700, + size: 20, + ), + SizedBox(width: 8), AppText( - TranslationBase.of(context).showMoreBtn, - textDecoration: TextDecoration.underline, + TranslationBase.of(context).showAttachment, color: Colors.red.shade700, fontSize: SizeConfig.textMultiplier! * 1.4, - fontWeight: FontWeight.w700, ), ], ), ), - ], + ), ), ), + SizedBox(height: 8,) ], ), ), + + // Label (e.g. "Diagnosis:") - bold + underlined, like the screenshot + Row( + children: [ + Expanded( + child: AppText( + patientLabResultList[index].description!, + fontSize: SizeConfig.textMultiplier! * 1.9, + + color: Colors.black, + ), + ), + SizedBox( + width: 8, + ), + // Value - plain text below the label + AppText( + (patientLabResultList[index].resultValue ?? "") + (patientLabResultList[index].uOM != null ? " ${patientLabResultList[index].uOM}" : ""), + fontSize: SizeConfig.textMultiplier! * 1.8, + fontWeight: FontWeight.w400, + color: Colors.black87, + isCopyable: true, + ), + ], + ), + + Visibility( + visible: patientLabResultList[index].TestShortDescription != null , + child:Column( + children: [ + SizedBox( + height: 20, + ), + AppText( + patientLabResultList[index].TestShortDescription??"", + fontSize: SizeConfig.textMultiplier! * 1.3, + fontWeight: FontWeight.w400, + color: Colors.black87, + isCopyable: true, + ), + SizedBox( + height: 8, + ), + ], + ) ), SizedBox( height: 16, ), + Center( + child: InkWell( + onTap: () { + Navigator.push( + context, + FadePage( + page: FlowChartPage( + filterName: patientLabResultList.first.description!, + patientLabOrder: patientLabOrder, + patient: patient, + isInpatient: isInpatient, + ), + ), + ); + }, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.show_chart, + color: Colors.red.shade700, + size: 20, + ), + SizedBox(width: 8), + AppText( + TranslationBase.of(context).showMoreBtn, + color: Colors.red.shade700, + fontSize: SizeConfig.textMultiplier! * 1.4, + ), + ], + ), + ), + ), + ), + SizedBox( + height: 16, + ), + Visibility( + visible: (patientLabResultList[index].IsLabTestAttachment== true ) && (patientLabResultList[index].IsPackage == false), + child: Center( + child: InkWell( + onTap: () async { + final labWithAttachment = patientLabResultList.firstWhere( + (lab) => lab.IsLabTestAttachment ?? false, + ); + var labAccessNumber = labWithAttachment.LabAccessionNo; + + showUploadedDocumentsBottomSheet( + context, + documents: labWithAttachment.UploadedDocuments, + fileName: labWithAttachment.FileNameWithExtensionList, + labAccessNumber: labAccessNumber, + projectID: int.parse(labWithAttachment.projectID!), + setupID: labWithAttachment.setupID, + ); + }, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.description_outlined, + color: Colors.red.shade700, + size: 20, + ), + SizedBox(width: 8), + AppText( + TranslationBase.of(context).showAttachment, + color: Colors.red.shade700, + fontSize: SizeConfig.textMultiplier! * 1.4, + ), + ], + ), + ), + ), + ), + ), ], ); }), SizedBox( height: 8, ), - Divider(), ], ), ); @@ -357,13 +368,13 @@ class LabResultWidget extends StatelessWidget { } void showUploadedDocumentsBottomSheet( - BuildContext context, { - List? documents, - List? fileName, - String? labAccessNumber, - int? projectID, - String? setupID, - }) { + BuildContext context, { + List? documents, + List? fileName, + String? labAccessNumber, + int? projectID, + String? setupID, + }) { const double kItemHeight = 66.0; // ListTile with contentPadding: 10 final double screenHeight = MediaQuery.of(context).size.height; final double maxSheetHeight = screenHeight * 0.5; @@ -422,7 +433,7 @@ class LabResultWidget extends StatelessWidget { child: const Divider(height: 1, color: Colors.grey), ), itemBuilder: (context, index) { - final docName = documents?[index]?.fileName ?? fileName?[index]; + final docName = documents?[index].fileName ?? fileName?[index]; return ListTile( contentPadding: const EdgeInsets.all(10), diff --git a/lib/screens/patients/profile/lab_result/laboratory_result/laboratory_result_widget.dart b/lib/screens/patients/profile/lab_result/laboratory_result/laboratory_result_widget.dart index c5643fcc..445d7922 100644 --- a/lib/screens/patients/profile/lab_result/laboratory_result/laboratory_result_widget.dart +++ b/lib/screens/patients/profile/lab_result/laboratory_result/laboratory_result_widget.dart @@ -13,7 +13,8 @@ import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/errors/error_message.dart'; import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; + import 'package:provider/provider.dart'; class LaboratoryResultWidget extends StatefulWidget { @@ -35,6 +36,7 @@ class LaboratoryResultWidget extends StatefulWidget { class _LaboratoryResultWidgetState extends State { bool _isShowMoreGeneral = true; bool _isShowMore = true; + int expandedIndex = 0; late ProjectViewModel projectViewModel; @override @@ -51,15 +53,23 @@ class _LaboratoryResultWidgetState extends State { baseViewModel: model, child: SafeArea( child: Container( - margin: EdgeInsets.all(15), + margin: EdgeInsets.all(4), child: Column( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (model.labResultLists.isNotEmpty) + if (model.mappedLabResultList.isNotEmpty) Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(16.0), + ), + ), + child: Column( children: [ InkWell( @@ -73,13 +83,13 @@ class _LaboratoryResultWidgetState extends State { child: Container( padding: EdgeInsets.all(10.0), margin: EdgeInsets.only(left: 5, right: 5), - decoration: BoxDecoration( - shape: BoxShape.rectangle, - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - ), + // decoration: BoxDecoration( + // shape: BoxShape.rectangle, + // color: Colors.white, + // borderRadius: BorderRadius.all( + // Radius.circular(5.0), + // ), + // ), child: Row( children: [ Expanded( @@ -107,33 +117,34 @@ class _LaboratoryResultWidgetState extends State { AnimatedContainer( padding: EdgeInsets.all(10.0), margin: EdgeInsets.only(left: 5, right: 5), - decoration: BoxDecoration( - shape: BoxShape.rectangle, - color: Colors.white, - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(5.0), - bottomRight: Radius.circular(5.0), - ), - ), + // decoration: BoxDecoration( + // shape: BoxShape.rectangle, + // color: Colors.white, + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(5.0), + // bottomRight: Radius.circular(5.0), + // ), + // ), duration: Duration(milliseconds: 7000), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - ListView.builder( - itemCount: model.labResultLists.length, - scrollDirection: Axis.vertical, - physics: ScrollPhysics(), - shrinkWrap: true, - itemBuilder: (context, index) { - return LabResultWidget( - patientLabOrder: widget.patientLabOrder!, - filterName: model.labResultLists[index].filterName, - patientLabResultList: model.labResultLists[index].patientLabResultList, - patient: widget.patient!, - isInpatient: widget.isInpatient!, - model: model, - ); - }), + // ListView.builder( + // itemCount: model.mappedLabResultList.length, + // scrollDirection: Axis.vertical, + // physics: ScrollPhysics(), + // shrinkWrap: true, + // itemBuilder: (context, index) { + // return LabResultWidget( + // patientLabOrder: widget.patientLabOrder!, + // filterName: model.labResultLists[index].filterName, + // patientLabResultList: model.labResultLists[index].patientLabResultList, + // patient: widget.patient!, + // isInpatient: widget.isInpatient!, + // model: model, + // ); + // }), + mappedListDisplay(model) ], ), ), @@ -150,139 +161,85 @@ class _LaboratoryResultWidgetState extends State { height: 15, ), if (widget.details?.isNotEmpty == true) - Column( - children: [ - InkWell( - onTap: () { - setState(() { - _isShowMore = !_isShowMore; - }); - }, - child: Container( - padding: EdgeInsets.all(10.0), - margin: EdgeInsets.only(left: 5, right: 5), - decoration: BoxDecoration( - shape: BoxShape.rectangle, - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(5.0), - )), - child: Row( - children: [ - Expanded( - child: Container( - margin: EdgeInsets.only(left: 0, right: 0), - child: AppText( - TranslationBase.of(context).specialResult, - fontSize: SizeConfig.textMultiplier! * 2.3, - bold: false, - ))), - Container( - width: 25, - height: 25, - child: Icon( - _isShowMore ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, - color: Colors.grey[800], - size: 22, - ), - ) - ], + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(16.0), + )), + child: Column( + children: [ + InkWell( + onTap: () { + setState(() { + _isShowMore = !_isShowMore; + }); + }, + child: Container( + padding: EdgeInsets.all(10.0), + margin: EdgeInsets.only(left: 5, right: 5), + child: Row( + children: [ + Expanded( + child: Container( + margin: EdgeInsets.only(left: 0, right: 0), + child: AppText( + TranslationBase.of(context).specialResult, + fontSize: SizeConfig.textMultiplier! * 2.3, + bold: false, + ))), + Container( + width: 25, + height: 25, + child: Icon( + _isShowMore ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, + color: Colors.grey[800], + size: 22, + ), + ) + ], + ), ), ), - ), - if (_isShowMore) - AnimatedContainer( - padding: EdgeInsets.all(10.0), - margin: EdgeInsets.only(left: 5, right: 5), - decoration: BoxDecoration( - shape: BoxShape.rectangle, - color: Colors.white, - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(5.0), - bottomRight: Radius.circular(5.0), - )), - duration: Duration(milliseconds: 7000), - child: ListView.separated( - separatorBuilder: (context, index) => Divider( - color: Colors.grey[300], - thickness: 1, - ), - itemCount: widget.details?.length ?? 0, - shrinkWrap: true, - physics: NeverScrollableScrollPhysics(), - itemBuilder: (context, index) { - String? resultData; - try { - resultData = (widget.details?[index])?.resultDataHTML?.toString(); - } catch (_) { - resultData = null; - } - final displayData = (resultData == null || resultData.trim().isEmpty) - ? TranslationBase.of(context).noDataAvailable - : resultData; - - return Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - !Utils.isTextHtml(displayData) - ? AppText(displayData) - : Html(data: displayData), - ], - ), - ), - Visibility( - visible: widget.details?[index].IsLabTestAttachment ?? false, - child: InkWell( - onTap: () async { - var labAccessNumber = widget.details?[index].LabAccessionNo; - // if (widget.details?[index].FileNameWithExtensionList?.isNotEmpty == true || widget.details?[index].FileNameWithExtensionList?.length == 1) { - // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: widget.details?[index].FileNameWithExtensionList?.first); - // model.openPDF(); - // return; - // } - // - // if (widget.details?[index].UploadedDocuments?.isNotEmpty == true || widget.details?[index].UploadedDocuments?.length == 1) { - // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: widget.details?[index].UploadedDocuments?.first); - // model.openPDF(); - // return; - // } + if (_isShowMore) + AnimatedContainer( + padding: EdgeInsets.all(10.0), + margin: EdgeInsets.only(left: 5, right: 5), + // decoration: BoxDecoration( + // shape: BoxShape.rectangle, + // color: Colors.white, + // borderRadius: BorderRadius.only( + // bottomLeft: Radius.circular(5.0), + // bottomRight: Radius.circular(5.0), + // )), + duration: Duration(milliseconds: 7000), + child: ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.grey[300], + thickness: 1, + ), + itemCount: widget.details?.length ?? 0, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + String? resultData; + try { + resultData = (widget.details?[index])?.resultDataHTML?.toString(); + } catch (_) { + resultData = null; + } + final displayData = (resultData == null || resultData.trim().isEmpty) + ? TranslationBase.of(context).noDataAvailable + : resultData.trim(); - showUploadedDocumentsBottomSheet( - context, - model, - documents: widget.details?[index].UploadedDocuments, - fileName: widget.details?[index].FileNameWithExtensionList, - labAccessNumber: labAccessNumber, - projectID: int.parse(widget.details?[index].ProjectID??"0"), - setupID: widget.details?[index].SetupID); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AppText( - TranslationBase.of(context).showAttachment, - textDecoration: TextDecoration.underline, - color: Colors.red.shade700, - fontSize: SizeConfig.textMultiplier! * 1.2, - fontWeight: FontWeight.w700, - ), - ], - ), - ), - ), - - ], - ); - }, + return buildLabDetailItem(context, index, displayData, model); + }, + ), ), - ), - SizedBox( - height: 10, - ), - ], + + ], + ), ), ], ), @@ -294,6 +251,83 @@ class _LaboratoryResultWidgetState extends State { ), ); } + Widget buildLabDetailItem(BuildContext context, int index, String displayData, LabsViewModel model) { + return Card( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + elevation: 8, + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + !Utils.isTextHtml(displayData) + ? AppText(displayData) + : HtmlWidget(displayData), + Visibility( + visible: widget.details?[index].IsLabTestAttachment ?? false, + child: Column( + children: [ + SizedBox(height: 8,), + InkWell( + onTap: () async { + var labAccessNumber = widget.details?[index].LabAccessionNo; + // if (widget.details?[index].FileNameWithExtensionList?.isNotEmpty == true || widget.details?[index].FileNameWithExtensionList?.length == 1) { + // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: widget.details?[index].FileNameWithExtensionList?.first); + // model.openPDF(); + // return; + // } + // + // if (widget.details?[index].UploadedDocuments?.isNotEmpty == true || widget.details?[index].UploadedDocuments?.length == 1) { + // await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: widget.details?[index].UploadedDocuments?.first); + // model.openPDF(); + // return; + // } + + showUploadedDocumentsBottomSheet( + context, + model, + documents: widget.details?[index].UploadedDocuments, + fileName: widget.details?[index].FileNameWithExtensionList, + labAccessNumber: labAccessNumber, + projectID: int.parse(widget.details?[index].ProjectID ?? "0"), + setupID: widget.details?[index].SetupID); + }, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(16), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.description_outlined, + color: Colors.red.shade700, + size: 20, + ), + SizedBox(width: 8), + AppText( + TranslationBase.of(context).showAttachment, + color: Colors.red.shade700, + fontSize: SizeConfig.textMultiplier! * 1.4, + ), + ], + ), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } void showUploadedDocumentsBottomSheet( BuildContext context, LabsViewModel model, { @@ -361,7 +395,7 @@ class _LaboratoryResultWidgetState extends State { child: const Divider(height: 1, color: Colors.grey), ), itemBuilder: (context, index) { - final docName = documents?[index]?.fileName ?? fileName?[index]; + final docName = documents?[index].fileName ?? fileName?[index]; return ListTile( contentPadding: const EdgeInsets.all(10), @@ -403,4 +437,104 @@ class _LaboratoryResultWidgetState extends State { }, ); } + + mappedListDisplay(LabsViewModel model) { + final packageEntries = model.mappedLabResultList.entries.toList(); + return ListView.separated( + separatorBuilder: (_, __) => Padding(padding: EdgeInsets.all(4), + child: Divider( + height: 2, + ) ,), + physics: NeverScrollableScrollPhysics(), + padding: EdgeInsets.zero, + shrinkWrap: true, + itemCount: packageEntries.length, + itemBuilder: (context, packageIndex) { + final packageName = packageEntries[packageIndex].key; + final labResults = packageEntries[packageIndex].value; + final isExpanded = expandedIndex == packageIndex; + + return InkWell( + onTap: () { + setState(() { + if (isExpanded) { + expandedIndex = -1; // Collapse if already expanded + } else + expandedIndex = packageIndex; + }); + }, + child: Card( + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + elevation: 2, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Row( + children: [ + Expanded( + child: Container( + margin: EdgeInsets.only(left: 0, right: 0), + child: AppText( + packageName, + fontSize: SizeConfig.textMultiplier! * 1.8, + bold: false, + ))), + // Arrow rotates smoothly between down/up instead of snapping + AnimatedRotation( + turns: isExpanded ? 0.5 : 0.0, + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOut, + child: Container( + width: 25, + height: 25, + child: Icon( + Icons.keyboard_arrow_down, + color: Colors.grey[800], + size: 22, + ), + ), + ) + ], + ), + + + // Animated expand/collapse of the lab result content + AnimatedSize( + duration: const Duration(milliseconds: 250), + curve: Curves.easeInOut, + alignment: Alignment.topCenter, + child: AnimatedCrossFade( + duration: const Duration(milliseconds: 250), + sizeCurve: Curves.easeInOut, + firstCurve: Curves.easeIn, + secondCurve: Curves.easeIn, + crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst, + firstChild: const SizedBox(width: double.infinity, height: 0), + secondChild: Column( + mainAxisSize: MainAxisSize.min, + children: [ + LabResultWidget( + patientLabOrder: widget.patientLabOrder!, + filterName: "", + patientLabResultList: labResults, + patient: widget.patient!, + isInpatient: widget.isInpatient!, + model: model, + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); + } } diff --git a/lib/screens/patients/profile/lab_result/special_result/special_lab_result_details_page.dart b/lib/screens/patients/profile/lab_result/special_result/special_lab_result_details_page.dart index 45ecd2b8..674798ea 100644 --- a/lib/screens/patients/profile/lab_result/special_result/special_lab_result_details_page.dart +++ b/lib/screens/patients/profile/lab_result/special_result/special_lab_result_details_page.dart @@ -3,6 +3,7 @@ import 'package:doctor_app_flutter/core/viewModel/PatientMedicalReportViewModel. import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart'; import 'package:doctor_app_flutter/core/viewModel/labs_view_model.dart'; import 'package:doctor_app_flutter/screens/base/base_view.dart'; +import 'package:doctor_app_flutter/utils/extenstions_utils.dart'; import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart'; import 'package:doctor_app_flutter/widgets/patients/profile/app_bar/patient-profile-app-bar.dart'; import 'package:doctor_app_flutter/widgets/patients/patient_service_title.dart'; @@ -10,8 +11,8 @@ import 'package:doctor_app_flutter/widgets/shared/app_scaffold_widget.dart'; import 'package:doctor_app_flutter/widgets/shared/errors/error_message.dart'; import 'package:doctor_app_flutter/widgets/shared/network_base_view.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; +// import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import '../../../../../config/size_config.dart'; import '../../../../../core/model/labs/lab_result.dart'; @@ -52,29 +53,68 @@ class SpecialLabResultDetailsPage extends StatelessWidget { child: Column( children: [ (resultData != null && resultData.isNotEmpty) - ? Container( - width: double.infinity, - margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16), - padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.all(Radius.circular(8)), - border: Border.fromBorderSide( - BorderSide( - color: Colors.white, - width: 1.0, - ), - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Html(data: resultData ?? ""), - HtmlWidget(resultData ?? ""), - Visibility( - visible: labResult.IsLabTestAttachment ?? false, - child: InkWell( + ? Card( + color: Colors.white, + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + elevation: 4, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + + Visibility( + visible: labResult.testDescription != null && (labResult.testDescription as String).isNotEmpty , + child:Column( + children: [ + SizedBox( + height: 8, + ), + AppText( + labResult.testDescription ??"", + fontSize: SizeConfig.textMultiplier! * 1.6, + fontWeight: FontWeight.w700, + color: Colors.black87, + isCopyable: true, + ), + SizedBox( + height: 8, + ), + ], + ) ), + Visibility( + visible: labResult.testShortDescription != null && (labResult.testShortDescription as String).isNotEmpty , + child:Column( + children: [ + SizedBox( + height: 8, + ), + AppText( + labResult.testShortDescription ??"", + fontSize: SizeConfig.textMultiplier! * 1.3, + fontWeight: FontWeight.w400, + color: Colors.black87, + isCopyable: true, + ), + SizedBox( + height: 8, + ), + ], + ) ), + // Html(data: resultData ?? ""), + HtmlWidget(resultData ?? ""), + + Visibility( + visible: labResult.IsLabTestAttachment ?? false, + child: Column( + children: [ + SizedBox( + height: 12, + ), + InkWell( onTap: () async { var labAccessNumber = labResult.LabAccessionNo; // if (patientLabResultList[index].FileNameWithExtensionList?.isNotEmpty == true || patientLabResultList[index].FileNameWithExtensionList?.length == 1) { @@ -89,32 +129,49 @@ class SpecialLabResultDetailsPage extends StatelessWidget { // return; // } - showUploadedDocumentsBottomSheet(context, - documents: labResult.UploadedDocuments, - fileName: labResult.FileNameWithExtensionList, - labAccessNumber: labAccessNumber, - projectID: int.parse(labResult.projectID!), - // projectID: 160, - setupID: labResult.setupID, - model: model); - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AppText( - TranslationBase - .of(context) - .showAttachment, - textDecoration: TextDecoration.underline, - color: Colors.red.shade700, - fontSize: SizeConfig.textMultiplier! * 1.2, - fontWeight: FontWeight.w700, + showUploadedDocumentsBottomSheet( + context, + documents: labResult.UploadedDocuments, + fileName: labResult.FileNameWithExtensionList, + labAccessNumber: labAccessNumber, + projectID: int.parse(labResult.projectID!), + // projectID: 160, + setupID: labResult.setupID, + model: model, + ); + }, + child: Container( + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 14, horizontal: 16), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.description_outlined, + color: Colors.red.shade700, + size: 18, + ), + SizedBox(width: 6), + AppText( + TranslationBase.of(context).showAttachment, + color: Colors.red.shade700, + fontSize: SizeConfig.textMultiplier! * 1.4, + fontWeight: FontWeight.w400, + ), + ], + ), + ), ), ], ), ), - ), - ], + ], + ), ), ) : Container( diff --git a/lib/screens/patients/profile/medical_report/AddVerifyMedicalReport.dart b/lib/screens/patients/profile/medical_report/AddVerifyMedicalReport.dart index d7228b00..3be59abc 100644 --- a/lib/screens/patients/profile/medical_report/AddVerifyMedicalReport.dart +++ b/lib/screens/patients/profile/medical_report/AddVerifyMedicalReport.dart @@ -10,9 +10,12 @@ import 'package:doctor_app_flutter/widgets/shared/buttons/app_buttons_widget.dar import 'package:doctor_app_flutter/widgets/shared/loader/gif_loader_dialog_utils.dart'; import 'package:doctor_app_flutter/widgets/shared/text_fields/html_rich_editor.dart'; import 'package:flutter/material.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:flutter_quill/flutter_quill.dart'; +import 'package:flutter_quill_delta_from_html/parser/html_to_delta.dart'; +// import 'package:html_editor_plus/editor_plus.dart'; +// import 'package:html_editor_enhanced/html_editor.dart'; import 'package:permission_handler/permission_handler.dart'; - +import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart'; import '../../../../config/config.dart'; class AddVerifyMedicalReport extends StatefulWidget { @@ -32,7 +35,8 @@ class AddVerifyMedicalReport extends StatefulWidget { } class _AddVerifyMedicalReportState extends State { - HtmlEditorController _controller = HtmlEditorController(); + QuillController _controller = QuillController.basic(); + @override Widget build(BuildContext context) { @@ -41,6 +45,11 @@ class _AddVerifyMedicalReportState extends State { return BaseView( onModelReady: (model) async { model.getMedicalReportTemplate(); + _controller = htmlToQuillController(widget.medicalReport != null + ? widget.medicalNote! + : widget.model!.medicalReportTemplate[0].templateText!.length > 0 + ? widget.model!.medicalReportTemplate[0].templateText! + : ""); }, builder: (_, model, w) => AppScaffold( baseViewModel: model, @@ -62,14 +71,10 @@ class _AddVerifyMedicalReportState extends State { children: [ if (model.medicalReportTemplate.length > 0) HtmlRichEditor( - initialText: (widget.medicalReport != null - ? widget.medicalNote! - : widget.model!.medicalReportTemplate[0].templateText!.length > 0 - ? widget.model!.medicalReportTemplate[0].templateText! - : ""), - controller: _controller, + initialText:"", hint: "Write the medical report ", height: MediaQuery.of(context).size.height * 0.75, + controller:_controller ), ], ), @@ -93,7 +98,10 @@ class _AddVerifyMedicalReportState extends State { // disabled: progressNoteController.text.isEmpty, fontWeight: FontWeight.w700, onPressed: () async { - txtOfMedicalReport = (await _controller.getText())!; + final converter = QuillDeltaToHtmlConverter( + List.castFrom(_controller.document.toDelta().toJson()), + ); + txtOfMedicalReport = converter.convert(); if (txtOfMedicalReport.isNotEmpty) { GifLoaderDialogUtils.showMyDialog(context); @@ -125,7 +133,10 @@ class _AddVerifyMedicalReportState extends State { color: AppGlobal.appGreenColor, fontWeight: FontWeight.w700, onPressed: () async { - txtOfMedicalReport = (await _controller.getText())!; + final converter = QuillDeltaToHtmlConverter( + List.castFrom(_controller.document.toDelta().toJson()), + ); + txtOfMedicalReport = converter.convert(); if (txtOfMedicalReport.isNotEmpty) { GifLoaderDialogUtils.showMyDialog(context); print("isVidaPlusProject: ${widget.isVidaPlusProject}"); @@ -154,6 +165,17 @@ class _AddVerifyMedicalReportState extends State { Permission.microphone, ].request(); } + QuillController htmlToQuillController(String html) { + if(html.isEmpty) { + return QuillController.basic(); + } + final delta = HtmlToDelta().convert(html); + return QuillController( + document: Document.fromDelta(delta), + selection: const TextSelection.collapsed(offset: 0), + ); + } } + enum MedicalReportStatus { ADD, VERIFY } diff --git a/lib/screens/patients/profile/medical_report/MedicalReportDetailPage.dart b/lib/screens/patients/profile/medical_report/MedicalReportDetailPage.dart index 03631a3b..55d1aae3 100644 --- a/lib/screens/patients/profile/medical_report/MedicalReportDetailPage.dart +++ b/lib/screens/patients/profile/medical_report/MedicalReportDetailPage.dart @@ -10,7 +10,7 @@ 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/errors/error_message.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:provider/provider.dart'; class MedicalReportDetailPage extends StatelessWidget { @@ -74,7 +74,7 @@ class MedicalReportDetailPage extends StatelessWidget { ), ), ), - child: Html(data: medicalReport.reportDataHtml ?? ""), + child: HtmlWidget(medicalReport.reportDataHtml ?? ""), ) : Container( child: ErrorMessage( diff --git a/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart b/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart index 59303bb0..b03adb8c 100644 --- a/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart +++ b/lib/screens/patients/profile/vital_sign/LineChartCurvedBloodPressure.dart @@ -139,7 +139,7 @@ class LineChartCurvedBloodPressureNew extends StatelessWidget { return LineChartData( lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( - tooltipBgColor: Colors.white, + getTooltipColor: (LineBarSpot touchedSpot) => Colors.white, ), touchCallback: (touchEvent, LineTouchResponse? touchResponse) {}, handleBuiltInTouches: true, diff --git a/lib/screens/patients/profile/vital_sign/line_chart_curved.dart b/lib/screens/patients/profile/vital_sign/line_chart_curved.dart index 51cc3bb9..5ec16e1c 100644 --- a/lib/screens/patients/profile/vital_sign/line_chart_curved.dart +++ b/lib/screens/patients/profile/vital_sign/line_chart_curved.dart @@ -100,7 +100,7 @@ class LineChartCurved extends StatelessWidget { return LineChartData( lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( - tooltipBgColor: Colors.white, + getTooltipColor: (LineBarSpot touchedSpot) => Colors.white, ), touchCallback: (event, LineTouchResponse? touchResponse) {}, handleBuiltInTouches: true, diff --git a/lib/screens/patients/profile/vital_sign/line_chart_curved_blood_pressure.dart b/lib/screens/patients/profile/vital_sign/line_chart_curved_blood_pressure.dart index e843a4d1..69e71e26 100644 --- a/lib/screens/patients/profile/vital_sign/line_chart_curved_blood_pressure.dart +++ b/lib/screens/patients/profile/vital_sign/line_chart_curved_blood_pressure.dart @@ -119,7 +119,7 @@ class LineChartCurvedBloodPressure extends StatelessWidget { return LineChartData( lineTouchData: LineTouchData( touchTooltipData: LineTouchTooltipData( - tooltipBgColor: Colors.white, + getTooltipColor: (LineBarSpot touchedSpot) => Colors.white, ), touchCallback: (event, LineTouchResponse? touchResponse) {}, handleBuiltInTouches: true, diff --git a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart index 8bd67c48..5631e419 100644 --- a/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart +++ b/lib/screens/pharmacy_intervention/widgets/PharmacyInterventionDialog.dart @@ -6,8 +6,8 @@ import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; -import '../../../widgets/shared/app_texts_widget.dart'; import '../../patients/profile/soap_update_vida_plus/assessment/widget/empty_dropdown.dart'; +import 'package:material_ui/material_ui.dart' as decoration; class PharmacyInterventionDialog extends StatefulWidget { final Function( @@ -281,40 +281,36 @@ class _PharmacyInterventionDialogState child: EmptyDropDown()) : Expanded( child: DropdownSearch( - itemAsString:(item){ - return item.description??''; - } , - items: widget.station?.entityList ?? [], + itemAsString: (item) => item.description ?? '', + items: (filter, loadProps) => widget.station?.entityList ?? [], + compareFn: (a, b) => a.description == b.description, // see notes popupProps: PopupProps.menu( showSearchBox: true, - searchDelay: Duration(microseconds: 100), + searchDelay: const Duration(milliseconds: 100), searchFieldProps: TextFieldProps( - decoration: InputDecoration( - border: UnderlineInputBorder(), - hintText: TranslationBase.of(context).search - ) - ) + decoration: decoration.InputDecoration( + border: decoration.UnderlineInputBorder(), + hintText: TranslationBase.of(context).search, + ), + ), ), - dropdownButtonProps: DropdownButtonProps(color: AppGlobal.appRedColor,), - dropdownDecoratorProps: DropDownDecoratorProps( - textAlignVertical: TextAlignVertical.center, - dropdownSearchDecoration: InputDecoration( - border: InputBorder.none + suffixProps: DropdownSuffixProps( + dropdownButtonProps: DropdownButtonProps( + iconClosed: Icon(Icons.arrow_drop_down, color: AppGlobal.appRedColor), + iconOpened: Icon(Icons.arrow_drop_up, color: AppGlobal.appRedColor), ), - baseStyle: TextStyle( - fontSize: 14 - ) ), - - selectedItem: nursingStation == null - ? widget.station?.entityList?.first - : nursingStation, - onChanged: (newValue) async { - if (newValue != null) - setState(() { - nursingStation = newValue ; - }); - }, + decoratorProps: DropDownDecoratorProps( + textAlignVertical: TextAlignVertical.center, + baseStyle: TextStyle(fontSize: 14), + decoration: decoration.InputDecoration(border: decoration.InputBorder.none), + ), + selectedItem: nursingStation ?? widget.station?.entityList?.firstOrNull, + onSelected: (newValue) { + if (newValue != null) { + setState(() => nursingStation = newValue); + } + }, ) // DropdownButtonHideUnderline( // child: DropdownButton( diff --git a/lib/screens/reschedule_leaves/reschedule_leave.dart b/lib/screens/reschedule_leaves/reschedule_leave.dart index 5169097b..3c306fbf 100644 --- a/lib/screens/reschedule_leaves/reschedule_leave.dart +++ b/lib/screens/reschedule_leaves/reschedule_leave.dart @@ -21,6 +21,7 @@ import 'package:flutter/material.dart'; import 'package:hexcolor/hexcolor.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; +import 'package:material_ui/material_ui.dart' as decoration; Utils helpers = Utils(); @@ -424,52 +425,60 @@ class _RescheduleLeaveScreen extends State { model2.coveringDoctors.length > 0 ? Expanded( // add Expanded to have your dropdown button fill remaining space - child: DropdownSearch( - dropdownButtonProps: DropdownButtonProps(), - dropdownDecoratorProps: DropDownDecoratorProps( - dropdownSearchDecoration: InputDecoration(contentPadding: EdgeInsets.all(0), border: InputBorder.none), + child: DropdownSearch( + items: (filter, loadProps) => model2.coveringDoctors + .map((item) => (projectsProvider.isArabic + ? item['doctorNameN'] + : item['doctorName']) + .toString()) + .toList(), + decoratorProps: const DropDownDecoratorProps( + decoration: decoration.InputDecoration( + contentPadding: EdgeInsets.zero, + border: decoration.InputBorder.none, + ), ), - - //maxHeight: 300, - items: model2.coveringDoctors.map((item) { - return projectsProvider.isArabic ? item['doctorNameN'] : item['doctorName']; - }).toList(), - // label: "Doctor List", - onChanged: (item) { - model2.coveringDoctors.forEach((newVal) => {if (newVal['doctorName'] == item) doctorID = newVal['DoctorID']}); - }, selectedItem: getSelectedDoctor(model2), + onSelected: (item) { + final nameKey = projectsProvider.isArabic ? 'doctorNameN' : 'doctorName'; + for (final doctor in model2.coveringDoctors) { + if (doctor[nameKey] == item) { + doctorID = doctor['DoctorID']; + } + } + }, popupProps: PopupProps.bottomSheet( - bottomSheetProps: BottomSheetProps( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(24), - topRight: Radius.circular(24), - ), + showSearchBox: true, + bottomSheetProps: const BottomSheetProps( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), ), ), - title: Container( - height: 50, - decoration: BoxDecoration( - color: Theme.of(context).primaryColorDark, - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), - ), + ), + title: Container( + height: 50, + decoration: BoxDecoration( + color: Theme.of(context).primaryColorDark, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), ), - child: Center( - child: Text( - '', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + ), + child: const Center( + child: Text( + '', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.white, ), ), ), - showSearchBox: true), - ), + ), + ), + ) ) : SizedBox(), ], diff --git a/lib/screens/video_call_zoom/zoom_video_call.dart b/lib/screens/video_call_zoom/zoom_video_call.dart index 747a3a91..23d16b16 100644 --- a/lib/screens/video_call_zoom/zoom_video_call.dart +++ b/lib/screens/video_call_zoom/zoom_video_call.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:doctor_app_flutter/screens/video_call_zoom/video_view.dart'; -import 'package:events_emitter/events_emitter.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -142,10 +141,10 @@ class _CallScreenState extends State { }); useEffect(() { - eventListener.addEventListener(); + EventEmitter emitter = eventListener.eventEmitter; - final sessionJoinListener = emitter.on(EventType.onSessionJoin, (sessionUser) async { + final sessionJoinListener = emitter.addListener(EventType.onSessionJoin, (sessionUser) async { isInSession.value = true; zoom.session.getSessionName().then((value) => sessionName.value = value!); sessionPassword.value = await zoom.session.getSessionPassword(); @@ -165,7 +164,7 @@ class _CallScreenState extends State { isReceiveSpokenLanguageContentEnabled.value = await zoom.liveTranscriptionHelper.isReceiveSpokenLanguageContentEnabled(); }); - final sessionLeaveListener = emitter.on(EventType.onSessionLeave, (data) async { + final sessionLeaveListener = emitter.addListener(EventType.onSessionLeave, (data) async { isInSession.value = false; users.value = []; fullScreenUser.value = null; @@ -173,7 +172,7 @@ class _CallScreenState extends State { Navigator.pop(context); }); - final sessionNeedPasswordListener = emitter.on(EventType.onSessionNeedPassword, (data) async { + final sessionNeedPasswordListener = emitter.addListener(EventType.onSessionNeedPassword, (data) async { showDialog( context: context, builder: (BuildContext context) => AlertDialog( @@ -193,7 +192,7 @@ class _CallScreenState extends State { ); }); - final sessionPasswordWrongListener = emitter.on(EventType.onSessionPasswordWrong, (data) async { + final sessionPasswordWrongListener = emitter.addListener(EventType.onSessionPasswordWrong, (data) async { showDialog( context: context, builder: (BuildContext context) => AlertDialog( @@ -213,7 +212,7 @@ class _CallScreenState extends State { ); }); - final userVideoStatusChangedListener = emitter.on(EventType.onUserVideoStatusChanged, (data) async { + final userVideoStatusChangedListener = emitter.addListener(EventType.onUserVideoStatusChanged, (data) async { data = data as Map; ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); var userListJson = jsonDecode(data['changedUsers']) as List; @@ -228,7 +227,7 @@ class _CallScreenState extends State { videoStatusFlag.value = !videoStatusFlag.value; }); - final userAudioStatusChangedListener = emitter.on(EventType.onUserAudioStatusChanged, (data) async { + final userAudioStatusChangedListener = emitter.addListener(EventType.onUserAudioStatusChanged, (data) async { data = data as Map; ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); var userListJson = jsonDecode(data['changedUsers']) as List; @@ -243,7 +242,7 @@ class _CallScreenState extends State { audioStatusFlag.value = !audioStatusFlag.value; }); - final userShareStatusChangeListener = emitter.on(EventType.onUserShareStatusChanged, (data) async { + final userShareStatusChangeListener = emitter.addListener(EventType.onUserShareStatusChanged, (data) async { data = data as Map; ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); ZoomVideoSdkUser shareUser = ZoomVideoSdkUser.fromJson(jsonDecode(data['user'].toString())); @@ -260,7 +259,7 @@ class _CallScreenState extends State { userShareStatusFlag.value = !userShareStatusFlag.value; }); - final userJoinListener = emitter.on(EventType.onUserJoin, (data) async { + final userJoinListener = emitter.addListener(EventType.onUserJoin, (data) async { if (!isMounted()) return; data = data as Map; ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); @@ -271,7 +270,7 @@ class _CallScreenState extends State { fullScreenUser.value = remoteUserList[1]; }); - final userLeaveListener = emitter.on(EventType.onUserLeave, (data) async { + final userLeaveListener = emitter.addListener(EventType.onUserLeave, (data) async { if (!isMounted()) return; ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); data = data as Map; @@ -294,7 +293,7 @@ class _CallScreenState extends State { users.value = remoteUserList; }); - final userNameChangedListener = emitter.on(EventType.onUserNameChanged, (data) async { + final userNameChangedListener = emitter.addListener(EventType.onUserNameChanged, (data) async { if (!isMounted()) return; data = data as Map; ZoomVideoSdkUser? changedUser = ZoomVideoSdkUser.fromJson(jsonDecode(data['changedUser'])); @@ -308,27 +307,27 @@ class _CallScreenState extends State { userNameFlag.value = !userNameFlag.value; }); - final commandReceived = emitter.on(EventType.onCommandReceived, (data) async { + final commandReceived = emitter.addListener(EventType.onCommandReceived, (data) async { data = data as Map; debugPrint("sender: ${ZoomVideoSdkUser.fromJson(jsonDecode(data['sender']))}, command: ${data['command']}"); }); - final chatDeleteMessageNotify = emitter.on(EventType.onChatDeleteMessageNotify, (data) async { + final chatDeleteMessageNotify = emitter.addListener(EventType.onChatDeleteMessageNotify, (data) async { data = data as Map; debugPrint("onChatDeleteMessageNotify: messageID: ${data['msgID']}, deleteBy: ${data['type']}"); }); - final liveStreamStatusChangeListener = emitter.on(EventType.onLiveStreamStatusChanged, (data) async { + final liveStreamStatusChangeListener = emitter.addListener(EventType.onLiveStreamStatusChanged, (data) async { data = data as Map; debugPrint("onLiveStreamStatusChanged: status: ${data['status']}"); }); - final liveTranscriptionStatusChangeListener = emitter.on(EventType.onLiveTranscriptionStatus, (data) async { + final liveTranscriptionStatusChangeListener = emitter.addListener(EventType.onLiveTranscriptionStatus, (data) async { data = data as Map; debugPrint("onLiveTranscriptionStatus: status: ${data['status']}"); }); - final cloudRecordingStatusListener = emitter.on(EventType.onCloudRecordingStatus, (data) async { + final cloudRecordingStatusListener = emitter.addListener(EventType.onCloudRecordingStatus, (data) async { data = data as Map; debugPrint("onCloudRecordingStatus: status: ${data['status']}"); ZoomVideoSdkUser? mySelf = await zoom.session.getMySelf(); @@ -380,18 +379,18 @@ class _CallScreenState extends State { } }); - final liveTranscriptionMsgInfoReceivedListener = emitter.on(EventType.onLiveTranscriptionMsgInfoReceived, (data) async { + final liveTranscriptionMsgInfoReceivedListener = emitter.addListener(EventType.onLiveTranscriptionMsgInfoReceived, (data) async { data = data as Map; ZoomVideoSdkLiveTranscriptionMessageInfo? messageInfo = ZoomVideoSdkLiveTranscriptionMessageInfo.fromJson(jsonDecode(data['messageInfo'])); debugPrint("onLiveTranscriptionMsgInfoReceived: content: ${messageInfo.messageContent}"); }); - final inviteByPhoneStatusListener = emitter.on(EventType.onInviteByPhoneStatus, (data) async { + final inviteByPhoneStatusListener = emitter.addListener(EventType.onInviteByPhoneStatus, (data) async { data = data as Map; debugPrint("onInviteByPhoneStatus: status: ${data['status']}, reason: ${data['reason']}"); }); - final multiCameraStreamStatusChangedListener = emitter.on(EventType.onMultiCameraStreamStatusChanged, (data) async { + final multiCameraStreamStatusChangedListener = emitter.addListener(EventType.onMultiCameraStreamStatusChanged, (data) async { data = data as Map; ZoomVideoSdkUser? changedUser = ZoomVideoSdkUser.fromJson(jsonDecode(data['changedUser'])); var status = data['status']; @@ -408,7 +407,7 @@ class _CallScreenState extends State { } }); - final requireSystemPermission = emitter.on(EventType.onRequireSystemPermission, (data) async { + final requireSystemPermission = emitter.addListener(EventType.onRequireSystemPermission, (data) async { data = data as Map; ZoomVideoSdkUser? changedUser = ZoomVideoSdkUser.fromJson(jsonDecode(data['changedUser'])); var permissionType = data['permissionType']; @@ -446,7 +445,7 @@ class _CallScreenState extends State { } }); - final networkStatusChangeListener = emitter.on(EventType.onUserVideoNetworkStatusChanged, (data) async { + final networkStatusChangeListener = emitter.addListener(EventType.onUserVideoNetworkStatusChanged, (data) async { data = data as Map; ZoomVideoSdkUser? networkUser = ZoomVideoSdkUser.fromJson(jsonDecode(data['user'])); @@ -455,7 +454,7 @@ class _CallScreenState extends State { } }); - final eventErrorListener = emitter.on( + final eventErrorListener = emitter.addListener( EventType.onError, (data) async { data = data as Map; @@ -487,24 +486,24 @@ class _CallScreenState extends State { }, ); - final userRecordingConsentListener = emitter.on(EventType.onUserRecordingConsent, (data) async { + final userRecordingConsentListener = emitter.addListener(EventType.onUserRecordingConsent, (data) async { data = data as Map; ZoomVideoSdkUser? user = ZoomVideoSdkUser.fromJson(jsonDecode(data['user'])); debugPrint('userRecordingConsentListener: user= ${user.userName}'); }); - final callCRCDeviceStatusListener = emitter.on(EventType.onCallCRCDeviceStatusChanged, (data) async { + final callCRCDeviceStatusListener = emitter.addListener(EventType.onCallCRCDeviceStatusChanged, (data) async { data = data as Map; debugPrint('onCallCRCDeviceStatusChanged: status = ${data['status']}'); }); - final originalLanguageMsgReceivedListener = emitter.on(EventType.onOriginalLanguageMsgReceived, (data) async { + final originalLanguageMsgReceivedListener = emitter.addListener(EventType.onOriginalLanguageMsgReceived, (data) async { data = data as Map; ZoomVideoSdkLiveTranscriptionMessageInfo? messageInfo = ZoomVideoSdkLiveTranscriptionMessageInfo.fromJson(jsonDecode(data['messageInfo'])); debugPrint("onOriginalLanguageMsgReceived: content: ${messageInfo.messageContent}"); }); - final chatPrivilegeChangedListener = emitter.on(EventType.onChatPrivilegeChanged, (data) async { + final chatPrivilegeChangedListener = emitter.addListener(EventType.onChatPrivilegeChanged, (data) async { data = data as Map; String type = data['privilege']; debugPrint('chatPrivilegeChangedListener: type= $type'); diff --git a/lib/widgets/auth/sms-popup.dart b/lib/widgets/auth/sms-popup.dart index 98668ae1..0c36dad7 100644 --- a/lib/widgets/auth/sms-popup.dart +++ b/lib/widgets/auth/sms-popup.dart @@ -48,6 +48,7 @@ class SMSOTP { late ProjectViewModel projectProvider; String displayTime = ''; bool isClosed = false; + // final TurnstileController _controller = TurnstileController(); // final TurnstileOptions _options = TurnstileOptions( // size: TurnstileSize.normal, @@ -58,6 +59,7 @@ class SMSOTP { // ); String? _token; + displayDialog(BuildContext context) async { double dialogWidth = MediaQuery.of(context).size.width * 0.90; double dialogInputWidth = (dialogWidth / 4) - (SizeConfig.isWidthLarge ? SizeConfig.getWidthMultiplier(width: dialogWidth) * 4.5 : 20); @@ -76,8 +78,8 @@ class SMSOTP { child: Container( color: Colors.white, child: StatefulBuilder(builder: (context, setState) { - if (displayTime == '') { - startTimer(setState); + if (displayTime == '' && context.mounted) { + startTimer(setState, context); } return Center( @@ -246,7 +248,6 @@ class SMSOTP { )), ), ), - Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ AppText( TranslationBase.of(context).validationMessage + ' ', @@ -264,34 +265,38 @@ class SMSOTP { fontSize: SizeConfig.getTextMultiplierBasedOnWidth(width: dialogWidth) * 3.5, ) ]), - SizedBox(height: 10,), - Column(children: [ - // CloudflareTurnstile( - // siteKey: '0x4AAAAAAAkmbvEy63pcxBBt', - // baseUrl: BASE_URL, - // options: _options, - // controller: _controller, - // onTokenReceived: (token) { - // setState(() { - // print("Cloudflare token: $token"); - // //todo pass this token to checkActivcationCode - // _token = token; - // checkValue(); - // }); - // }, - // // onTokenRecived: (token) { - // // setState(() { - // // print("Cloudflare token: $token"); - // // _token = token; - // // }); - // // }, - // onTokenExpired: () {}, - // // mode: TurnstileMode.managed, - // // errorBuilder: (context, error) { - // // return Text(error.message); - // // }, - // ), - ],), + SizedBox( + height: 10, + ), + Column( + children: [ + // CloudflareTurnstile( + // siteKey: '0x4AAAAAAAkmbvEy63pcxBBt', + // baseUrl: BASE_URL, + // options: _options, + // controller: _controller, + // onTokenReceived: (token) { + // setState(() { + // print("Cloudflare token: $token"); + // //todo pass this token to checkActivcationCode + // _token = token; + // checkValue(); + // }); + // }, + // // onTokenRecived: (token) { + // // setState(() { + // // print("Cloudflare token: $token"); + // // _token = token; + // // }); + // // }, + // onTokenExpired: () {}, + // // mode: TurnstileMode.managed, + // // errorBuilder: (context, error) { + // // return Text(error.message); + // // }, + // ), + ], + ), ], ), ), @@ -344,7 +349,8 @@ class SMSOTP { } checkValue() async { - if (verifyAccountForm.currentState!.validate() ) { //&& _token !=null removed cloud flare for vida plus + if (verifyAccountForm.currentState!.validate()) { + //&& _token !=null removed cloud flare for vida plus // if (digit1.text.isNotEmpty && digit2.text.isNotEmpty && digit3.text.isNotEmpty && digit4.text.isNotEmpty) { onSuccess(digit1.text.toString() + digit2.text.toString() + digit3.text.toString() + digit4.text.toString()); this.isClosed = true; @@ -363,8 +369,11 @@ class SMSOTP { return minutesString + ":" + secondsString; } - startTimer(setState) { + startTimer(setState, BuildContext context) { this.remainingTime--; + if (context.mounted == false) { + return; + } setState(() { displayTime = this.getSecondsAsDigitalClock(this.remainingTime); }); @@ -372,7 +381,7 @@ class SMSOTP { Future.delayed(Duration(seconds: 1), () { if (this.remainingTime > 0) { if (isClosed == false) { - startTimer(setState); + startTimer(setState,context); } } else { Navigator.pop(context); diff --git a/lib/widgets/shared/text_fields/html_rich_editor.dart b/lib/widgets/shared/text_fields/html_rich_editor.dart index cef783bc..e66c7db1 100644 --- a/lib/widgets/shared/text_fields/html_rich_editor.dart +++ b/lib/widgets/shared/text_fields/html_rich_editor.dart @@ -4,11 +4,14 @@ 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/utils/translations_delegate_base_utils.dart'; import 'package:flutter/material.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:flutter_quill/flutter_quill.dart'; +import 'package:flutter_quill_delta_from_html/parser/html_to_delta.dart'; + import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:speech_to_text/speech_recognition_error.dart'; import 'package:speech_to_text/speech_to_text.dart' as stt; +import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart'; import '../speech-text-popup.dart'; @@ -19,8 +22,8 @@ class HtmlRichEditor extends StatefulWidget { final BoxDecoration? decoration; final bool darkMode; final bool showBottomToolbar; - final List? toolbar; - final HtmlEditorController? controller; + final dynamic toolbar; + final QuillController? controller; HtmlRichEditor({ key, @@ -63,34 +66,68 @@ class _HtmlRichEditorState extends State { return Stack( children: [ - HtmlEditor( - controller: widget.controller!, - htmlToolbarOptions: HtmlToolbarOptions(defaultToolbarButtons: [ - StyleButtons(), - FontSettingButtons(), - FontButtons(), - // ColorButtons(), - ListButtons(), - ParagraphButtons(), - // InsertButtons(), - // OtherButtons(), - ]), - htmlEditorOptions: HtmlEditorOptions( - hint: widget.hint, - initialText: widget.initialText, - darkMode: widget.darkMode, + // Toolbar + Column( + children: [ + QuillSimpleToolbar( + controller: widget.controller!, + + config: const QuillSimpleToolbarConfig( + showFontFamily: false, + showSearchButton: false, + showSubscript: false, + showSuperscript: false, + + multiRowsDisplay: false, // single scrollable row + ), + ), + const Divider(height: 1), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: QuillEditor( + controller: widget.controller!, + focusNode: FocusNode(), + + scrollController:ScrollController(), + config: const QuillEditorConfig( + placeholder: 'Start writing...', + padding: EdgeInsets.symmetric(vertical: 12), + expands: false, + autoFocus: false, + ), + ), ), - otherOptions: OtherOptions( - height: widget.height, - decoration: widget.decoration ?? - BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.all( - Radius.circular(30.0), - ), - border: Border.all(color: Colors.grey[200]!, width: 0.5), - ), - )), + ], + ), + // HtmlEditor( + // controller: widget.controller!, + // // htmlToolbarOptions: HtmlToolbarOptions(defaultToolbarButtons: [ + // // StyleButtons(), + // // FontSettingButtons(), + // // FontButtons(), + // // // ColorButtons(), + // // ListButtons(), + // // ParagraphButtons(), + // // // InsertButtons(), + // // // OtherButtons(), + // // ]), + // // htmlEditorOptions: HtmlEditorOptions( + // // hint: widget.hint, + // // initialText: widget.initialText, + // // darkMode: widget.darkMode, + // // ), + // // otherOptions: OtherOptions( + // // height: widget.height, + // // decoration: widget.decoration ?? + // // BoxDecoration( + // // color: Colors.transparent, + // // borderRadius: BorderRadius.all( + // // Radius.circular(30.0), + // // ), + // // border: Border.all(color: Colors.grey[200]!, width: 0.5), + // // ), + // // ) + // ), Positioned( top: 50, //MediaQuery.of(context).size.height * 0, right: projectViewModel.isArabic ? MediaQuery.of(context).size.width * 0.75 : 15, @@ -142,10 +179,10 @@ class _HtmlRichEditorState extends State { void resultListener(result) async { recognizedWord = result.recognizedWords; event.setValue({"searchText": recognizedWord}); - String txt = await widget.controller!.getText(); + String txt = _getHtml(); if (result.finalResult == true) { setState(() { - widget.controller!.setText(txt + recognizedWord); + appendToEnd(widget.controller!, recognizedWord); SpeechToText.closeAlertDialog(context); // speech.stop(); }); @@ -154,6 +191,23 @@ class _HtmlRichEditorState extends State { } } + void appendToEnd(QuillController controller, String text) { + final index = controller.document.length - 1; // position before the final '\n' + controller.replaceText( + index, + 0, + text, + TextSelection.collapsed(offset: index + text.length), + ); + } + + String _getHtml() { + final delta = List>.from( + widget.controller!.document.toDelta().toJson(), + ); + return QuillDeltaToHtmlConverter(delta, ConverterOptions()).convert(); + } + Future initSpeechState() async { bool hasSpeech = await speech.initialize(onError: errorListener, onStatus: statusListener); print(hasSpeech); diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index dbec55e5..fe111402 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,10 +6,14 @@ #include "generated_plugin_registrant.h" +#include #include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) maps_launcher_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "MapsLauncherPlugin"); maps_launcher_plugin_register_with_registrar(maps_launcher_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 6c56d5b0..65e9a3db 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,11 +3,13 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux maps_launcher url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index f28a37b3..b0ce34e3 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,28 +5,44 @@ import FlutterMacOS import Foundation +import audio_session import connectivity_plus +import file_picker_darwin +import file_selector_macos import firebase_analytics import firebase_core import firebase_messaging -import flutter_inappwebview_macos +import just_audio +import local_auth_darwin import maps_launcher -import path_provider_foundation +import package_info_plus +import quill_native_bridge_macos import shared_preferences_foundation import speech_to_text import sqflite_darwin import url_launcher_macos +import video_player_avfoundation +import wakelock_plus +import webview_flutter_wkwebview func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin")) ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) - FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) + FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) - InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) + JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) + LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) MapsLauncherPlugin.register(with: registry.registrar(forPlugin: "MapsLauncherPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + QuillNativeBridgePlugin.register(with: registry.registrar(forPlugin: "QuillNativeBridgePlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SpeechToTextPlugin.register(with: registry.registrar(forPlugin: "SpeechToTextPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + VideoPlayerPlugin.register(with: registry.registrar(forPlugin: "VideoPlayerPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) + WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) } diff --git a/macos/Podfile b/macos/Podfile index b52666a1..b15254e3 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.15' +platform :osx, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index b5fb56ba..9dfd467e 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -557,7 +557,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -639,7 +639,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -689,7 +689,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/pubspec.lock b/pubspec.lock index ff2fdad7..d2c3d412 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,58 +5,66 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + sha256: fdcd9f70f9eb80df3bc5ed0fa67280df2595fd481948df8a9ab082e6a40ad04b url: "https://pub.dev" source: hosted - version: "64.0.0" + version: "108.0.0" _flutterfire_internals: dependency: transitive description: name: _flutterfire_internals - sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" + sha256: f6966125633a34f82d9be2ee895b755cff3554087b1d00a9eb884e5947f4bca9 url: "https://pub.dev" source: hosted - version: "1.3.25" - adaptive_number: + version: "1.3.77" + analyzer: dependency: transitive description: - name: adaptive_number - sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77" + name: analyzer + sha256: a51c769bff3b6dfbe9d60199b8606d808290702a296bef0c26a4ca391d414e46 url: "https://pub.dev" source: hosted - version: "1.0.0" - analyzer: + version: "14.4.0" + android_file_picker: dependency: transitive description: - name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + name: android_file_picker + sha256: "14ab27769b54c48d5a8a71aa9858372b7a3ae77572ea0a8aee744643c5d8c53d" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "2.0.0" archive: dependency: transitive description: name: archive - sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + sha256: "6c5bcd986e06b94e3c40244af471750840a3d2341d1f9763a1100a14add517b4" url: "https://pub.dev" source: hosted - version: "3.6.1" + version: "4.3.0" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.7.0" async: dependency: transitive description: name: async - sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 url: "https://pub.dev" source: hosted - version: "2.12.0" + version: "2.13.1" + audio_session: + dependency: transitive + description: + name: audio_session + sha256: f9e7711a0e24ca8b40f5d7ac374c3c6e55016f3157912badd18199cdbbca5c4d + url: "https://pub.dev" + source: hosted + version: "0.2.4" autocomplete_textfield: dependency: "direct main" description: @@ -69,26 +77,26 @@ packages: dependency: "direct main" description: name: badges - sha256: a7b6bbd60dce418df0db3058b53f9d083c22cdb5132a052145dc267494df0b84 + sha256: "4d53519c5883c74974b8efd2ea3cef85bab17b79406b83b91a022285c46e5560" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "4.0.1" barcode_scan2: dependency: "direct main" description: name: barcode_scan2 - sha256: "0f3eb7c0a0c80a0f65d3fa88737544fdb6d27127a4fad566e980e626f3fb76e1" + sha256: dc58b90e9a6a7bb4f4a31bf8d0498f5ce53778c8e3784994e458d40ec134e38a url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "4.8.2" bazel_worker: dependency: transitive description: name: bazel_worker - sha256: "4eef19cc486c289e4b06c69d0f6f3192e85cc93c25d4d15d02afb205e388d2f0" + sha256: "87cae9150fcf9942b8057e5f51c4848a3efde1289e97411e1c8f01e350120999" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.5" boolean_selector: dependency: transitive description: @@ -101,98 +109,82 @@ packages: dependency: transitive description: name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + sha256: "8a5c5761af8e31748bba3c82f68925ace40f3225c3eea25be9beb57eca7cd7a8" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "4.0.11" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + sha256: d466ed2dc9c6cd1d169948879b84ee061eb5e22c64a7c6089879c6296d272a8d url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.3.3" build_daemon: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: e1d40ef3f7934986d5da2271b1ba07794921ce263e44d622fb6c406d76589e33 url: "https://pub.dev" source: hosted - version: "4.0.1" - build_resolvers: - dependency: transitive - description: - name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.dev" - source: hosted - version: "2.4.2" + version: "4.1.6" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" + sha256: "894c243f6bc32015fec466ce30a6925bd537a77a426ee5bf481120477eb3de67" url: "https://pub.dev" source: hosted - version: "2.4.9" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" - url: "https://pub.dev" - source: hosted - version: "7.3.0" + version: "2.16.1" build_web_compilers: dependency: "direct dev" description: name: build_web_compilers - sha256: c8be4b48f09289d145c7eaa3240f1e7776c529ea1cecddf483218edd3129de3f + sha256: f8136b4d19e55917711f134a5f4cf2fded7dfe97e4accf0c9a47b5d0fea4e296 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.8.11" built_collection: dependency: transitive description: name: built_collection - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + sha256: "44922ecebd8e3d0cef743dadd3b54df4e87e2a4c52a29465a1872aa9e192caa8" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.1.2" built_value: dependency: transitive description: name: built_value - sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + sha256: f87ea98192116f7093cb214551ce1929caae0681fdba282b3d8b4462adee7bb7 url: "https://pub.dev" source: hosted - version: "8.9.2" + version: "8.13.0" cached_network_image: dependency: "direct main" description: name: cached_network_image - sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + sha256: "64a6c35e63cfd22865238d11fe8608bb538306ece5b2eb951106280441fdbb0c" url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "4.0.4" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + sha256: "555e287d3882fbb36cde50d24214cb3f6a272d39c4386e8afe00cb188d35b285" url: "https://pub.dev" source: hosted - version: "4.1.1" + version: "5.0.3" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + sha256: "38762ec3bd2295f4d79545add118f525bd5a105a53692c06208c4875f2abde62" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "2.0.3" characters: dependency: transitive description: @@ -201,6 +193,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a + url: "https://pub.dev" + source: hosted + version: "1.4.0" charts_common: dependency: transitive description: @@ -221,26 +221,34 @@ packages: dependency: transitive description: name: checked_yaml - sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "2.0.4" + chewie: + dependency: transitive + description: + name: chewie + sha256: "56b6641693ddd72f0cd54ddfedf4f3e9390e6d7b7b22dc2503b7e6ad91476f7f" + url: "https://pub.dev" + source: hosted + version: "1.17.2" clock: dependency: transitive description: name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e url: "https://pub.dev" source: hosted - version: "1.1.2" - code_builder: + version: "1.1.3" + code_assets: dependency: transitive description: - name: code_builder - sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + name: code_assets + sha256: "828110d598123b5ea96c00c9f3c72105bf79f8ee36c20a39b26209ade421ec57" url: "https://pub.dev" source: hosted - version: "4.10.0" + version: "2.1.0" collection: dependency: transitive description: @@ -253,74 +261,90 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: "051849e2bd7c7b3bc5844ea0d096609ddc3a859890ec3a9ac4a65a2620cc1f99" + sha256: d7749fd36d8b404a4935612b94eca7c3ce3705377ab678e24ff2a4301436f741 url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "7.3.2" connectivity_plus_platform_interface: dependency: transitive description: name: connectivity_plus_platform_interface - sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + sha256: "3c09627c536d22fd24691a905cdd8b14520de69da52c7a97499c8be5284a32ed" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.0" convert: dependency: transitive description: name: convert - sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.1.2" cross_file: dependency: transitive description: name: cross_file - sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + sha256: f141ea4f277af142a0356955707f6556f37b03947d39d55585981a06ca437bd6 url: "https://pub.dev" source: hosted - version: "0.3.4+2" + version: "0.3.5+5" crypto: dependency: transitive description: name: crypto - sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.7" csslib: dependency: transitive description: name: csslib - sha256: "831883fb353c8bdc1d71979e5b342c7d88acfbc643113c14ae51e2442ea0f20f" + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" url: "https://pub.dev" source: hosted - version: "0.17.3" + version: "1.0.2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + url: "https://pub.dev" + source: hosted + version: "1.0.9" + cupertino_ui: + dependency: transitive + description: + name: cupertino_ui + sha256: c23816577a1280cff409e989541767887011f8f1d8c1863a794ed308af46f2a9 url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.1.1" dart_jsonwebtoken: dependency: "direct main" description: name: dart_jsonwebtoken - sha256: "00a0812d2aeaeb0d30bcbc4dd3cee57971dbc0ab2216adf4f0247f37793f15ef" + sha256: ad84e60181696513d04d5f2078e0bbc20365b911f46f647797317414bdc88fbe url: "https://pub.dev" source: hosted - version: "2.17.0" + version: "3.4.1" + dart_quill_delta: + dependency: transitive + description: + name: dart_quill_delta + sha256: bddb0b2948bd5b5a328f1651764486d162c59a8ccffd4c63e8b2c5e44be1dac4 + url: "https://pub.dev" + source: hosted + version: "10.8.3" dart_style: dependency: transitive description: name: dart_style - sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + sha256: "82ade9fc4273f29ed673e33166944465225b4f7fc5d4aaef48605cc751c18fc1" url: "https://pub.dev" source: hosted - version: "2.3.6" + version: "3.1.13" date_time_picker: dependency: "direct main" description: @@ -333,34 +357,34 @@ packages: dependency: transitive description: name: dbus - sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + sha256: f7db8504e715b835f5ebe5fe74604ccd961d504c73389a5d8e81bafc2e2f3612 url: "https://pub.dev" source: hosted - version: "0.7.11" - dropdown_search: - dependency: "direct main" + version: "0.8.0" + diff_match_patch: + dependency: transitive description: - name: dropdown_search - sha256: "55106e8290acaa97ed15bea1fdad82c3cf0c248dd410e651f5a8ac6870f783ab" + name: diff_match_patch + sha256: "2efc9e6e8f449d0abe15be240e2c2a3bcd977c8d126cfd70598aee60af35c0a4" url: "https://pub.dev" source: hosted - version: "5.0.6" - ed25519_edwards: - dependency: transitive + version: "0.4.1" + dropdown_search: + dependency: "direct main" description: - name: ed25519_edwards - sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd" + name: dropdown_search + sha256: "4e78b97da7dd85c82533feadebbe1fd52038351ca3818ea200a9943958bdf01c" url: "https://pub.dev" source: hosted - version: "0.3.1" + version: "8.1.0" equatable: dependency: transitive description: name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + sha256: "3bce007a596ff8b3119c45d68aaef631272537c03d30e5d4534dd24bf4c5eaa2" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.1.0" eva_icons_flutter: dependency: "direct main" description: @@ -369,14 +393,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" - events_emitter: - dependency: transitive - description: - name: events_emitter - sha256: a075477bdf9c8c0c31bb7c7b7bdd357b4486c34f30163119f96de4e7f54abeff - url: "https://pub.dev" - source: hosted - version: "0.5.2" expandable: dependency: "direct main" description: @@ -397,10 +413,18 @@ packages: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.0" + ffi_leak_tracker: + dependency: transitive + description: + name: ffi_leak_tracker + sha256: "4093d4ef9ca06ffe2786e73bfb25e22aa92112b9bb4ec941f11e3e6b61489a97" + url: "https://pub.dev" + source: hosted + version: "0.1.2" file: dependency: transitive description: @@ -413,114 +437,162 @@ packages: dependency: "direct main" description: name: file_picker - sha256: aac85f20436608e01a6ffd1fdd4e746a7f33c93a2c83752e626bdfaea139b877 + sha256: "98c0b156b6380ba55bc767a14e2e6b3feb246e713ad40092424596fa79005bea" + url: "https://pub.dev" + source: hosted + version: "13.1.0" + file_picker_darwin: + dependency: transitive + description: + name: file_picker_darwin + sha256: "51aef9f4c80449c736e7cc02198675fda73689f0bd45a84da642cfeab0250d46" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file_picker_linux: + dependency: transitive + description: + name: file_picker_linux + sha256: "9c870771500c758eb46506c98532c3ee60e6e51d0a62dcde24a849ef213ea5ce" + url: "https://pub.dev" + source: hosted + version: "2.0.1" + file_picker_platform_interface: + dependency: transitive + description: + name: file_picker_platform_interface + sha256: bbdc085a6f168e63f147e9ce8988f79fa0800a58e7f25a48f762c60837107ba5 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + file_picker_web: + dependency: transitive + description: + name: file_picker_web + sha256: b3004268da0c1b52baa18df430e7ec4438194de855a807d26b447cbf07ef3496 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: da76400e7872ce7637ffdce12749ec24169c25f6195c28372208e65a24bcd2ab + url: "https://pub.dev" + source: hosted + version: "0.9.4+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: d57c62362766b5e7ae739448650b66c6aab7a68ba7ecc65e04018652645ae0f4 url: "https://pub.dev" source: hosted - version: "8.1.3" + version: "0.9.5+1" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" + url: "https://pub.dev" + source: hosted + version: "2.7.0" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: fbefc5fb92c6d3cbe8d284a2cd971b593bb07d2cd6da8557b81a862250b4acec + url: "https://pub.dev" + source: hosted + version: "0.9.3+6" firebase_analytics: dependency: "direct main" description: name: firebase_analytics - sha256: b13cbf1ee78744ca5e6b762e9218db3bd3967a0edfed75f58339907892a2ccb9 + sha256: b82d2cabf4905a465ac95937037cbab4f2ca80f559cb04abd3da3f2abb9960bb url: "https://pub.dev" source: hosted - version: "10.8.9" + version: "12.6.0" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "416b33d62033db5ecd2df719fcb657ad04e9995fa0fc392ffdab4ca0e76cb679" + sha256: "5c3ab4b681c837afd71f0abf77c7485f51c7b645d4ae77b96f9ed54779ff4126" url: "https://pub.dev" source: hosted - version: "3.9.9" + version: "6.0.7" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "9dca9d8d468172444ef18cabb73fe99f7aae24733bfad67115bd36bffd2d65c1" + sha256: "09eb4d0ce4c9a16efbc277ac709a90eb197d5512592215a73c6a302ab1ab6c3a" url: "https://pub.dev" source: hosted - version: "0.5.5+21" + version: "0.6.1+13" firebase_core: dependency: transitive description: name: firebase_core - sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" + sha256: "5fbbaa2aeb08a52feee559f92a62f5a6b04c9bdff81c8f608636771cf0d7b680" url: "https://pub.dev" source: hosted - version: "2.27.0" + version: "4.15.0" firebase_core_platform_interface: dependency: transitive description: name: firebase_core_platform_interface - sha256: f7d7180c7f99babd4b4c517754d41a09a4943a0f7a69b65c894ca5c68ba66315 + sha256: "9bfbc85faca09346471ac56fbcee00757ebcfd85887c6f602764eff0001902d8" url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "8.1.1" firebase_core_web: dependency: transitive description: name: firebase_core_web - sha256: f4ee170441ca141c5f9ee5ad8737daba3ee9c8e7efb6902aee90b4fbd178ce25 + sha256: "8ed84f5001dbd7a0390e2818d46bc858ceebb970edededdfc8d6552c76fc2f6e" url: "https://pub.dev" source: hosted - version: "2.18.0" + version: "3.12.0" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "980259425fa5e2afc03e533f33723335731d21a56fd255611083bceebf4373a8" + sha256: "47a8142a0b897783103b01018ad69f123b819b0120483847bde30d1b2fa89b36" url: "https://pub.dev" source: hosted - version: "14.7.10" + version: "16.7.0" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: f7a9d74ff7fc588a924f6b2eaeaa148b0db521b13a9db55f6ad45864fa98c06e + sha256: f9707e185b8ce1155d58e7e29348245072d99981f899fa8d3214abb2652c4ccb url: "https://pub.dev" source: hosted - version: "4.5.27" + version: "4.10.0" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: "90dc7ed885e90a24bb0e56d661d4d2b5f84429697fd2cbb9e5890a0ca370e6f4" + sha256: "311b16c75fc645c7a70c9ade38908abb12310dfce449fc3d3cee1771f196351e" url: "https://pub.dev" source: hosted - version: "3.5.18" + version: "4.2.5" fixnum: dependency: transitive description: name: fixnum - sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" fl_chart: dependency: "direct main" description: name: fl_chart - sha256: "5a74434cc83bf64346efb562f1a06eefaf1bcb530dc3d96a104f631a1eff8d79" - url: "https://pub.dev" - source: hosted - version: "0.65.0" - flex_color_picker: - dependency: transitive - description: - name: flex_color_picker - sha256: "5c846437069fb7afdd7ade6bf37e628a71d2ab0787095ddcb1253bf9345d5f3a" + sha256: b938f77d042cbcd822936a7a359a7235bad8bd72070de1f827efc2cc297ac888 url: "https://pub.dev" source: hosted - version: "3.4.1" - flex_seed_scheme: - dependency: transitive - description: - name: flex_seed_scheme - sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01" - url: "https://pub.dev" - source: hosted - version: "1.5.0" + version: "1.2.0" flutter: dependency: "direct main" description: flutter @@ -530,10 +602,10 @@ packages: dependency: transitive description: name: flutter_cache_manager - sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + sha256: f94fc6f5480977e3eb7b622ed488f671ba96c971bd0e274e6bd0f0ba9b044816 url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "3.4.5" flutter_colorpicker: dependency: "direct main" description: @@ -546,10 +618,10 @@ packages: dependency: "direct main" description: name: flutter_datetime_picker_plus - sha256: "7d82da02c4e070bb28a9107de119ad195e2319b45c786fecc13482a9ffcc51da" + sha256: "5a1b046c8a8472cb9932d81d883f9d9b4e42beb96a792cb3c7a47852bda33792" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "3.0.1" flutter_device_type: dependency: "direct main" description: @@ -566,86 +638,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.20.5" - flutter_html: - dependency: "direct main" - description: - name: flutter_html - sha256: "02ad69e813ecfc0728a455e4bf892b9379983e050722b1dce00192ee2e41d1ee" - url: "https://pub.dev" - source: hosted - version: "3.0.0-beta.2" - flutter_inappwebview: - dependency: transitive - description: - name: flutter_inappwebview - sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5" - url: "https://pub.dev" - source: hosted - version: "6.1.5" - flutter_inappwebview_android: - dependency: transitive - description: - name: flutter_inappwebview_android - sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba" - url: "https://pub.dev" - source: hosted - version: "1.1.3" - flutter_inappwebview_internal_annotations: - dependency: transitive - description: - name: flutter_inappwebview_internal_annotations - sha256: "5f80fd30e208ddded7dbbcd0d569e7995f9f63d45ea3f548d8dd4c0b473fb4c8" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - flutter_inappwebview_ios: - dependency: transitive - description: - name: flutter_inappwebview_ios - sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_macos: - dependency: transitive - description: - name: flutter_inappwebview_macos - sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1 - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_platform_interface: - dependency: transitive - description: - name: flutter_inappwebview_platform_interface - sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500 - url: "https://pub.dev" - source: hosted - version: "1.3.0+1" - flutter_inappwebview_web: - dependency: transitive - description: - name: flutter_inappwebview_web - sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598" - url: "https://pub.dev" - source: hosted - version: "1.1.2" - flutter_inappwebview_windows: - dependency: transitive - description: - name: flutter_inappwebview_windows - sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055" - url: "https://pub.dev" - source: hosted - version: "0.6.0" - flutter_keyboard_visibility: - dependency: transitive - description: - name: flutter_keyboard_visibility - sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" - url: "https://pub.dev" - source: hosted - version: "6.0.0" flutter_keyboard_visibility_linux: dependency: transitive description: @@ -670,14 +662,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" - flutter_keyboard_visibility_web: + flutter_keyboard_visibility_temp_fork: dependency: transitive description: - name: flutter_keyboard_visibility_web - sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + name: flutter_keyboard_visibility_temp_fork + sha256: e3d02900640fbc1129245540db16944a0898b8be81694f4bf04b6c985bed9048 url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "0.1.5" flutter_keyboard_visibility_windows: dependency: transitive description: @@ -695,10 +687,10 @@ packages: dependency: "direct main" description: name: flutter_math_fork - sha256: "94bee4642892a94939af0748c6a7de0ff8318feee588379dcdfea7dc5cba06c8" + sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.4" flutter_plugin_android_lifecycle: dependency: "direct overridden" description: @@ -707,6 +699,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.27" + flutter_quill: + dependency: "direct main" + description: + name: flutter_quill + sha256: "1f773f5f75e2628d80361c2c840c592791a0a157ebd587c9e37cf2cb8b8519b7" + url: "https://pub.dev" + source: hosted + version: "11.6.0" + flutter_quill_delta_from_html: + dependency: "direct main" + description: + name: flutter_quill_delta_from_html + sha256: "0eb801ea8dd498cadc057507af5da794d4c9599ce58b2569cb3d4bb53ba8bed2" + url: "https://pub.dev" + source: hosted + version: "1.5.3" + flutter_quill_extensions: + dependency: "direct main" + description: + name: flutter_quill_extensions + sha256: "099dbaa962d14ac562eb028fd24d37670338352863044b7751fe642a2d2de938" + url: "https://pub.dev" + source: hosted + version: "11.0.0" flutter_staggered_grid_view: dependency: "direct main" description: @@ -719,10 +735,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f" url: "https://pub.dev" source: hosted - version: "2.0.10+1" + version: "2.3.0" flutter_swiper_view: dependency: "direct main" description: @@ -741,22 +757,38 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_widget_from_html: + dependency: "direct main" + description: + name: flutter_widget_from_html + sha256: "16fedbf9cc41656d50a2d27b7ef196bfe85c3fcecb2c84e69e288a1fb2154a1b" + url: "https://pub.dev" + source: hosted + version: "0.17.4" + flutter_widget_from_html_core: + dependency: transitive + description: + name: flutter_widget_from_html_core + sha256: "530f2e3cc57be1a00f8bfae1b0000064e8a6df0cf1fb4d48a80f85afde9b39b7" + url: "https://pub.dev" + source: hosted + version: "0.17.4" flutter_zoom_videosdk: dependency: "direct main" description: name: flutter_zoom_videosdk - sha256: bb800c733c3a0a31909b2834922e75e089108980154ba1e60ef881c0e21b8802 + sha256: "87caad07b994f09b9d8c4b8054c0dff5659029abae38dd6ec223460c3f1bcb7d" url: "https://pub.dev" source: hosted - version: "1.12.10" + version: "2.5.10" fluttertoast: dependency: "direct main" description: name: fluttertoast - sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1" + sha256: a5c39007e19fff5eeb7810d5be651c02bb5a1c06104bdd203b037bbfe49bd827 url: "https://pub.dev" source: hosted - version: "8.2.12" + version: "10.0.2" font_awesome_flutter: dependency: "direct main" description: @@ -769,26 +801,66 @@ packages: dependency: "direct main" description: name: freerasp - sha256: afba9e2ec1b578450701345230e87fda54e95c2f448154fbca55cf993f1ab2b3 + sha256: c730ee9d65a96651d756d8bb247f3ac5213828170ac15d517bfabceb40c7bd54 url: "https://pub.dev" source: hosted - version: "8.2.1" - frontend_server_client: + version: "8.2.3" + fwfh_cached_network_image: dependency: transitive description: - name: frontend_server_client - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + name: fwfh_cached_network_image + sha256: abbe8f65f3468bfdede4e450b2afffbdc0363f12bf0bdfef3815d47625446bb4 url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "0.16.3" + fwfh_chewie: + dependency: transitive + description: + name: fwfh_chewie + sha256: ae74fc26798b0e74f3983f7b851e74c63b9eeb2d3015ecd4b829096b2c3f8818 + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_just_audio: + dependency: transitive + description: + name: fwfh_just_audio + sha256: dfd622a0dfe049ac647423a2a8afa7f057d9b2b93d92710b624e3d370b1ac69a + url: "https://pub.dev" + source: hosted + version: "0.17.0" + fwfh_svg: + dependency: transitive + description: + name: fwfh_svg + sha256: "2e6bb241179eeeb1a7941e05c8c923b05d332d36a9085233e7bf110ea7deb915" + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_url_launcher: + dependency: transitive + description: + name: fwfh_url_launcher + sha256: c38aa8fb373fda3a89b951fa260b539f623f6edb45eee7874cb8b492471af881 + url: "https://pub.dev" + source: hosted + version: "0.16.1" + fwfh_webview: + dependency: transitive + description: + name: fwfh_webview + sha256: a9cdfbe58a7152bcc91c420dc96cd9972c01b5d1318a6d4c6d9a1d97a1bd6e94 + url: "https://pub.dev" + source: hosted + version: "0.15.8" get_it: dependency: "direct main" description: name: get_it - sha256: e6017ce7fdeaf218dc51a100344d8cb70134b80e28b760f8bb23c242437bafd7 + sha256: "2b5c6b077aad30bba9782178baff6076a2044141f1d5f2f15b43bca3fbe74874" url: "https://pub.dev" source: hosted - version: "7.6.7" + version: "9.3.0" gif: dependency: "direct main" description: @@ -801,90 +873,162 @@ packages: dependency: transitive description: name: glob - sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + sha256: "218aeb56050c714f62a3182775320dfa04602b55074873e24e31bbd39bda96fb" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.2.0" graphs: dependency: transitive description: name: graphs - sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" hexcolor: dependency: "direct main" description: name: hexcolor - sha256: c07f4bbb9095df87eeca87e7c69e8c3d60f70c66102d7b8d61c4af0453add3f6 + sha256: "235555a30d5817a88df1cb4eb72c0c3b448f9aafb848d9f01857c2214d3e77b0" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.1.3" hijri: dependency: transitive description: name: hijri - sha256: "203eb7341e32789af6429877e88411b1526ef44c5d157ce4d3b930dd32c37ef1" + sha256: b3f754c35bfa87fb53a5b5066e6390faf85200198a7d1b25f8dae1f14b96c47a url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "3.0.1" hijri_picker: dependency: "direct main" description: name: hijri_picker - sha256: "15dd1716f3bd0b72122a71740b3ec9bc623463b11e0c907602d2b7598f851984" + sha256: "7e2855cd402d6a82c3924f55b9d8ff707f5d88fdfca657ce4da0cb1b6d0c71e3" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "5.0.0" + hooks: + dependency: transitive + description: + name: hooks + sha256: eaac480a35ec0814146c2c48d96aaa829e0e44a7662c88ae84c9edf4bc35651f + url: "https://pub.dev" + source: hosted + version: "2.2.0" html: dependency: "direct main" description: name: html - sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a" + sha256: "43b67b8f43321ab066817dfac5619596c98bb1b61624e77203bb4351785f9699" url: "https://pub.dev" source: hosted - version: "0.15.4" - html_editor_enhanced: - dependency: "direct main" + version: "0.15.7" + html_unescape: + dependency: transitive description: - name: html_editor_enhanced - sha256: "5ae6cd965cca77f7186efccc47ca353799e831b31bd71438687a56131bbcd3a5" + name: html_unescape + sha256: "15362d7a18f19d7b742ef8dcb811f5fd2a2df98db9f80ea393c075189e0b61e3" url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.0.0" http: dependency: "direct main" description: name: http - sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" url: "https://pub.dev" source: hosted - version: "1.2.2" + version: "1.6.0" http_interceptor: dependency: "direct main" description: - name: http_interceptor - sha256: fc7eedc62433c17612bf65237a8aa2615553cc9130f1e4d75f7e5fa364d5232e + name: http_interceptor + sha256: bf7044578984ee9a0a90bc7c03fc08252912bff56b34cb9437e1a5696ca1271b + url: "https://pub.dev" + source: hosted + version: "3.0.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: d8402284df184bc05f4a2210c6c23983b0720f4cd87cbd05c5390a78af602667 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "8a7823d5d3e884f7780829d85d92110d072bdcd9ed48e2be158d2abe91a912d4" + url: "https://pub.dev" + source: hosted + version: "0.8.13+25" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "815921d05ef87d64dc64e9f7f855967614a9a67086d0c60fa27d47a1cd9a8896" + url: "https://pub.dev" + source: hosted + version: "0.8.13+9" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" + url: "https://pub.dev" + source: hosted + version: "0.2.2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" url: "https://pub.dev" source: hosted - version: "2.0.0-beta.8" - http_multi_server: + version: "0.2.2+1" + image_picker_platform_interface: dependency: transitive description: - name: http_multi_server - sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + name: image_picker_platform_interface + sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" url: "https://pub.dev" source: hosted - version: "3.2.1" - http_parser: + version: "2.11.1" + image_picker_windows: dependency: transitive description: - name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + name: image_picker_windows + sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "0.2.2" infinite_listview: dependency: transitive description: @@ -905,10 +1049,18 @@ packages: dependency: transitive description: name: io - sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + sha256: "2635216ca6a737e60de577ffa1a48a0bec76ca8a62917cfc1bb88c14c570646f" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" + is_ios_simulator: + dependency: transitive + description: + name: is_ios_simulator + sha256: "01321f4f778ec931b5abc216e6922dccf51e3c5db8aef72b3874f6b4c5447374" + url: "https://pub.dev" + source: hosted + version: "1.0.1" jhijri: dependency: "direct main" description: @@ -925,22 +1077,62 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" - js: + jni: + dependency: transitive + description: + name: jni + sha256: "6b9ca0602fef0230e83149afbe3f9f8227e94f2bbe84a1da4f14d699742f402d" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: b2310cdd4c18c65c081ab141a41efa94aa26c65431803703ece51996f174f351 + url: "https://pub.dev" + source: hosted + version: "1.0.3" + jni_util: dependency: transitive description: - name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + name: jni_util + sha256: "1ba86da04a5f2bf18fde2edb235587e70c5b0fc5bd4ba955f46b00942c3fc35f" url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "1.0.0" json_annotation: dependency: transitive description: name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80" + url: "https://pub.dev" + source: hosted + version: "4.12.0" + just_audio: + dependency: transitive + description: + name: just_audio + sha256: e60aa97b233ddea025e13dfac59195207f528fa5e9e4a4a49a8c0766701e5fe6 + url: "https://pub.dev" + source: hosted + version: "0.10.6" + just_audio_platform_interface: + dependency: transitive + description: + name: just_audio_platform_interface + sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a" url: "https://pub.dev" source: hosted - version: "4.9.0" + version: "4.6.0" + just_audio_web: + dependency: transitive + description: + name: just_audio_web + sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663" + url: "https://pub.dev" + source: hosted + version: "0.4.16" leak_tracker: dependency: transitive description: @@ -965,62 +1157,46 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" - url: "https://pub.dev" - source: hosted - version: "4.0.0" - list_counter: - dependency: transitive - description: - name: list_counter - sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237 - url: "https://pub.dev" - source: hosted - version: "1.0.2" local_auth: dependency: "direct main" description: name: local_auth - sha256: "27679ed8e0d7daab2357db6bb7076359e083a56b295c0c59723845301da6aed9" + sha256: ecf24edf2283c509ecd217e3595f6f71034b68888d28ad1dae6bfa0857b816ac url: "https://pub.dev" source: hosted - version: "2.1.8" + version: "3.0.2" local_auth_android: dependency: "direct main" description: name: local_auth_android - sha256: "63ad7ca6396290626dc0cb34725a939e4cfe965d80d36112f08d49cf13a8136e" + sha256: "76c389998fe95cff4352644776ab5775f24ddd58f179dbf3df1b9c268cbbadc4" url: "https://pub.dev" source: hosted - version: "1.0.49" - local_auth_ios: + version: "2.2.0" + local_auth_darwin: dependency: transitive description: - name: local_auth_ios - sha256: "6dde47dc852bc0c8343cb58e66a46efb16b62eddf389ce103d4dacb0c6c40c71" + name: local_auth_darwin + sha256: b1b2d938cc3511512e552d92e782e055b8dc29c83e21c59e6ecfc6bd79ab0744 url: "https://pub.dev" source: hosted - version: "1.1.7" + version: "2.0.4" local_auth_platform_interface: dependency: transitive description: name: local_auth_platform_interface - sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a" + sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122 url: "https://pub.dev" source: hosted - version: "1.0.10" + version: "1.1.0" local_auth_windows: dependency: transitive description: name: local_auth_windows - sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 + sha256: d72b8a441e5e6a679902f87c51529fcce65f442d77598484cf35454c3d733eda url: "https://pub.dev" source: hosted - version: "1.0.11" + version: "2.0.2" localization: dependency: "direct main" description: @@ -1033,18 +1209,18 @@ packages: dependency: "direct main" description: name: logger - sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3 + sha256: "2a0dc097e7b01d942475bdd552356db2d0f768b05540bd4b2b53f1840f2239a7" url: "https://pub.dev" source: hosted - version: "2.6.2" + version: "2.8.0" logging: dependency: transitive description: name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.3.0" maps_launcher: dependency: "direct main" description: @@ -1053,14 +1229,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0+1" + markdown: + dependency: transitive + description: + name: markdown + sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9 + url: "https://pub.dev" + source: hosted + version: "7.3.1" matcher: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.20" material_color_utilities: dependency: transitive description: @@ -1069,22 +1253,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.0" + material_ui: + dependency: transitive + description: + name: material_ui + sha256: "32d98f11cf5942a095a8c3e01b03e4de3b17941437713dcf36b1088fb62e23d2" + url: "https://pub.dev" + source: hosted + version: "1.5.0" meta: dependency: transitive description: name: meta - sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349" + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.19.0" mime: dependency: transitive description: name: mime - sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + sha256: bd47de35f07e27267e69c8c8b22edf9473bfee170a60d60fcc93730c5144b7f6 url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "2.1.0" nested: dependency: transitive description: @@ -1097,10 +1289,10 @@ packages: dependency: transitive description: name: nm - sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + sha256: "2ae480aa3379716b8bb58dfebb168e2919394c92b629efaaa0baaa5d140786e6" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.6.0" numberpicker: dependency: "direct main" description: @@ -1109,22 +1301,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "5c80c2ad6e2c0397de5db38c6d653e69616a3397e13aa7633bf39eb668f2041b" + url: "https://pub.dev" + source: hosted + version: "9.6.2" octo_image: dependency: transitive description: name: octo_image - sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + sha256: "49c4f93afc10f1ad4fdef9db88fed9c65a8eb5d9ad0a4fa9b128d7fedeb41418" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" + open_filex: + dependency: "direct main" + description: + name: open_filex + sha256: "9976da61b6a72302cf3b1efbce259200cd40232643a467aac7370addf94d6900" + url: "https://pub.dev" + source: hosted + version: "4.7.0" package_config: dependency: transitive description: name: package_config - sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.0" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: "73ef2cd5c11a7548f9b7f6fc2a4f6113de2e64aa2a70de63feede95548822908" + url: "https://pub.dev" + source: hosted + version: "10.2.2" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: db762cb2f4f25ee60fb6359773861b0f199e00b90d237bd85a76a1e806b46ef4 + url: "https://pub.dev" + source: hosted + version: "4.1.0" path: dependency: transitive description: @@ -1137,50 +1361,50 @@ packages: dependency: transitive description: name: path_parsing - sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "1.1.0" path_provider: - dependency: "direct overridden" + dependency: "direct main" description: name: path_provider - sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" + sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825 url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "3b4c1fc3aa55ddc9cd4aa6759984330d5c8e66aa7702a6223c61540dc6380c37" + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" url: "https://pub.dev" source: hosted - version: "2.2.19" + version: "2.3.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.6.0" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + sha256: "58c2005f147315b11e9b4a7bc889cd5203e250cba8e3f012dae259b4972b5c16" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.3" path_provider_windows: dependency: transitive description: @@ -1189,86 +1413,86 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" - pedantic: - dependency: transitive - description: - name: pedantic - sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" - url: "https://pub.dev" - source: hosted - version: "1.11.1" percent_indicator: dependency: "direct main" description: name: percent_indicator - sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c + sha256: "157d29133bbc6ecb11f923d36e7960a96a3f28837549a20b65e5135729f0f9fd" url: "https://pub.dev" source: hosted - version: "4.2.3" + version: "4.2.5" permission_handler: dependency: "direct main" description: name: permission_handler - sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb" + sha256: e6bcecadfe40df6b888141f23cbaf6ba6c3da49fb33f6ff887d060dd48544fbd url: "https://pub.dev" source: hosted - version: "11.3.1" + version: "13.0.2" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "76e4ab092c1b240d31177bb64d2b0bea43f43d0e23541ec866151b9f7b2490fa" + sha256: b1ce660f4d0dcaffdf2605a19544c129fb5adda4e6fd039992ae356c4e437039 url: "https://pub.dev" source: hosted - version: "12.0.12" + version: "14.1.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0 + sha256: "066bbbc60031b63b916a3871e7bb4b6a8c5e7cec8146dafec53d1da304eff0a5" url: "https://pub.dev" source: hosted - version: "9.4.5" + version: "9.6.2" permission_handler_html: dependency: transitive description: name: permission_handler_html - sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d" + sha256: "6ea98b3f17f60d3b527f2647ed2ab4dc0f6bfe25b22cb1c363f5d8f62252f6ac" url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.1.4+1" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea + sha256: ed86a61c190258fdd65de395ea0632822e3415c1faec38eae0c31b479c28a531 url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.4.1" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" + sha256: caeae01858a0a7d2df67a445ac98e1ad95e55a0e77c73044f4e9b1c8c2289cbd url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.2" petitparser: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: "2f1564aadb14215e478563b5406cb80729d022158c01dc50c96013c2f7eb4790" + url: "https://pub.dev" + source: hosted + version: "7.1.0" + photo_view: + dependency: transitive + description: + name: photo_view + sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e" url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "0.15.0" platform: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: a36d119c13416516a7b5913fbe8af8531e11633d784c550b2125f76c758524ec url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.2.0" plugin_platform_interface: dependency: transitive description: @@ -1277,86 +1501,126 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pointer_interceptor: + pointycastle: dependency: transitive description: - name: pointer_interceptor - sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" + name: pointycastle + sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5" url: "https://pub.dev" source: hosted - version: "0.10.1+2" - pointer_interceptor_ios: + version: "4.0.0" + pool: dependency: transitive description: - name: pointer_interceptor_ios - sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 + name: pool + sha256: "4177f68c237ea2128d1bee66ac17b2ce05ba3dbaafcbdd54c5d40a39d0b6b11c" url: "https://pub.dev" source: hosted - version: "0.10.1" - pointer_interceptor_platform_interface: + version: "1.5.3" + posix: dependency: transitive description: - name: pointer_interceptor_platform_interface - sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" + name: posix + sha256: bc1bad54ad2b735816e31f8d4600cfde6c7839975085ddfbca48b6c9f7c4044e url: "https://pub.dev" source: hosted - version: "0.10.0+1" - pointer_interceptor_web: + version: "6.5.2" + protobuf: dependency: transitive description: - name: pointer_interceptor_web - sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" + name: protobuf + sha256: "13b6717366aa7ec3792dd62c19c7d33a785708224365f2db23c5ca01f1c1a0f2" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" url: "https://pub.dev" source: hosted - version: "0.10.2+1" - pointycastle: + version: "6.1.5+1" + pub_semver: dependency: transitive description: - name: pointycastle - sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" + name: pub_semver + sha256: "261236774e8b1d69cfc6b9eabbc96c40f25e7a2d6b171f3385d4f65d5734fb24" url: "https://pub.dev" source: hosted - version: "3.9.1" - pool: + version: "2.2.1" + pubspec_parse: dependency: transitive description: - name: pool - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + name: pubspec_parse + sha256: c38b81cbf34450b67e0265d73433569d12e34782e30ed769c9cc99c9d5f2e796 url: "https://pub.dev" source: hosted - version: "1.5.1" - protobuf: + version: "1.6.0" + quill_native_bridge: dependency: transitive description: - name: protobuf - sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + name: quill_native_bridge + sha256: "53c7ee4e900ce63fcf566391c5c20a939890cfcf000486d325f451869d23a281" url: "https://pub.dev" source: hosted - version: "3.1.0" - provider: - dependency: "direct main" + version: "11.2.0" + quill_native_bridge_android: + dependency: transitive description: - name: provider - sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + name: quill_native_bridge_android + sha256: "763f2066d252a10c04cc66add7b7fa967bae8d25aefcd180d5ac808f5af4d143" url: "https://pub.dev" source: hosted - version: "6.1.2" - pub_semver: + version: "0.0.2" + quill_native_bridge_ios: dependency: transitive description: - name: pub_semver - sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + name: quill_native_bridge_ios + sha256: "31f9a0a955f85fbcd2576fdb6feb1879c70d770980d7f0118b7f2c0621c6b745" url: "https://pub.dev" source: hosted - version: "2.1.4" - pubspec_parse: + version: "0.0.3" + quill_native_bridge_linux: dependency: transitive description: - name: pubspec_parse - sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + name: quill_native_bridge_linux + sha256: "310ba83ed5bc049033224e9be1e9433d9000e2ad1357c47ece9c0fbc61f4ecad" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "0.0.3" + quill_native_bridge_macos: + dependency: transitive + description: + name: quill_native_bridge_macos + sha256: "1c0631bd1e2eee765a8b06017c5286a4e829778f4585736e048eb67c97af8a77" + url: "https://pub.dev" + source: hosted + version: "0.0.1" + quill_native_bridge_platform_interface: + dependency: transitive + description: + name: quill_native_bridge_platform_interface + sha256: "8264a2bdb8a294c31377a27b46c0f8717fa9f968cf113f7dc52d332ed9c84526" + url: "https://pub.dev" + source: hosted + version: "0.0.2+1" + quill_native_bridge_web: + dependency: transitive + description: + name: quill_native_bridge_web + sha256: "7c723f6824b0250d7f33e8b6c23f2f8eb0103fe48ee7ebf47ab6786b64d5c05d" + url: "https://pub.dev" + source: hosted + version: "0.0.2" + quill_native_bridge_windows: + dependency: transitive + description: + name: quill_native_bridge_windows + sha256: a23cd4d0d4477188d2dd4bc6db886fe5cb27e2d555b94434bc2b471d5d7558f5 + url: "https://pub.dev" + source: hosted + version: "0.1.1" quiver: dependency: "direct main" description: @@ -1365,14 +1629,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.2.2" + record_use: + dependency: transitive + description: + name: record_use + sha256: "1cb8564af8d43b464294411db9217f5ec04891c6f22ee2c32d73ae05e88a6bd2" + url: "https://pub.dev" + source: hosted + version: "1.1.1" rxdart: dependency: transitive description: name: rxdart - sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" url: "https://pub.dev" source: hosted - version: "0.27.7" + version: "0.28.0" safe_device: dependency: "direct main" description: @@ -1393,74 +1665,74 @@ packages: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.5" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + sha256: "1e12aafe408aa50da80edfd679a2a6bf63ba7ab37c7fa98286da459a757b3399" url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.4.28" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + sha256: "2ec3934efa51e46117f23031cc141b8fc878e8525b94ec1ea4f7f586cf1b47ea" url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.7" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.3" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shelf: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -1470,90 +1742,90 @@ packages: dependency: transitive description: name: source_maps - sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + sha256: "14c2945847669b44089bb1222f66873d7ff7103c58911917f2a63c5a62327898" url: "https://pub.dev" source: hosted - version: "0.10.12" + version: "0.10.14" source_span: dependency: transitive description: name: source_span - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.1" + version: "1.10.2" speech_to_text: dependency: "direct main" description: name: speech_to_text - sha256: "130fde359c23a4da6c2a4f032eab43e4c2b57c9818fe93694c091dfbdca6ae70" + sha256: f2fabd017b5cb07f4e06d496b2d4b957e39534bc848f92b1e6acac80a10f4967 url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.5.0" speech_to_text_platform_interface: dependency: transitive description: name: speech_to_text_platform_interface - sha256: a1935847704e41ee468aad83181ddd2423d0833abe55d769c59afca07adb5114 + sha256: "7e447356be3074c471223c9d179ef3f822475350b67ca923ec71ab3bf2ede214" url: "https://pub.dev" source: hosted - version: "2.3.0" - sprintf: + version: "2.5.0" + speech_to_text_windows: dependency: transitive description: - name: sprintf - sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + name: speech_to_text_windows + sha256: "2d1d10565b23262386b453b33656299608dc7a66784453735d6c1318f13f44d7" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "1.0.1" sqflite: dependency: transitive description: name: sqflite - sha256: "2d7299468485dca85efeeadf5d38986909c5eb0cd71fd3db2c2f000e6c9454bb" + sha256: "54ad23e2a79c846b596b6c56cdd9c867ea58c288258402316b602f78df0cbfe0" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.4" sqflite_android: dependency: transitive description: name: sqflite_android - sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + sha256: "805b27c6fa10d8883253795e644818fbd5c87ce665459db84fbe71326cbb5421" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: "761b9740ecbd4d3e66b8916d784e581861fd3c3553eda85e167bc49fdb68f709" + sha256: "077e38e82c099534146a2fb31b608c2a3a4489a0f21d9af6b2f5c87b566a1ea0" url: "https://pub.dev" source: hosted - version: "2.5.4+6" + version: "2.5.13" sqflite_darwin: dependency: transitive description: name: sqflite_darwin - sha256: "22adfd9a2c7d634041e96d6241e6e1c8138ca6817018afc5d443fef91dcefa9c" + sha256: dbdda396f975f74d611ffd3e6fb280ee3ee4cd2319b89278533f427e0140cf0b url: "https://pub.dev" source: hosted - version: "2.4.1+1" + version: "2.4.4" sqflite_platform_interface: dependency: transitive description: name: sqflite_platform_interface - sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + sha256: c9177b2f3150ed0647b90a94307c28452fe0a5401863044216aed83addd6c7c5 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.2" stack_trace: dependency: transitive description: name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" url: "https://pub.dev" source: hosted - version: "1.12.1" + version: "1.12.2" sticky_headers: dependency: "direct main" description: @@ -1574,10 +1846,10 @@ packages: dependency: transitive description: name: stream_transform - sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + sha256: a00e5f18bffc764f923e7dec1038527f7fe7a1791361a7117f0358193f13d53a url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -1590,10 +1862,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + sha256: "397b146f97613b83d84bdccb439bc8d0f3aebb6c1d14a9641e6f24201c490b2d" url: "https://pub.dev" source: hosted - version: "3.1.0+1" + version: "3.4.2" term_glyph: dependency: transitive description: @@ -1606,26 +1878,18 @@ packages: dependency: transitive description: name: test_api - sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.11" + version: "0.7.12" timezone: dependency: "direct main" description: name: timezone - sha256: dd14a3b83cfd7cb19e7888f1cbc20f258b8d71b54c06f79ac585f14093a287d1 - url: "https://pub.dev" - source: hosted - version: "0.10.1" - timing: - dependency: transitive - description: - name: timing - sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + sha256: "981d1020d6ef8fe1e7b3de5054e5b25579ae7c403d7734adc508ffc47668e9cb" url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "0.11.1" tuple: dependency: transitive description: @@ -1638,58 +1902,58 @@ packages: dependency: "direct main" description: name: two_dimensional_scrollables - sha256: b6028c80e782e58a5d18f9491737aae4f70d72dc08050ac92006905c7c0b5e21 + sha256: "27ab607d5900b9907308367c76a62467c88b3ede3017fcbece3a2419dc51c3de" url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "0.5.5" typed_data: dependency: transitive description: name: typed_data - sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.4.0" url_launcher: dependency: "direct main" description: name: url_launcher - sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 + sha256: e8cc955c97e06df9879140a1fe301f3d493f01b7c62dec7f46834be31d7e9fda url: "https://pub.dev" source: hosted - version: "6.3.2" + version: "6.3.3" url_launcher_android: dependency: "direct main" description: name: url_launcher_android - sha256: "81777b08c498a292d93ff2feead633174c386291e35612f8da438d6e92c4447e" + sha256: "611e87fb320b70d1dd721dc46af89c98aceccea9b31fde49e084591414e0c610" url: "https://pub.dev" source: hosted - version: "6.3.20" + version: "6.3.33" url_launcher_ios: dependency: "direct main" description: name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" + sha256: "8faa1aab294f1ab4040b43660c887b0418d5fa4f0cffef76a484e6aa1092eb4a" url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.4.2" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + sha256: "10f86fef4c2c43563fa6c211ff9cf757adf4d3ab762c56bd430664a947d70cd0" url: "https://pub.dev" source: hosted - version: "3.1.1" + version: "3.2.3" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + sha256: "5e835a3b869c2d70325349c81c5a45c28e20791265b67b2669da6b08c5cd5201" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.2.6" url_launcher_platform_interface: dependency: transitive description: @@ -1702,130 +1966,234 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.4.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + sha256: "6c5ad3f22cd4c38e089b81963b3cd7bb83b111b2df5dce008bb066162f42e429" url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.6" uuid: dependency: transitive description: name: uuid - sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 + sha256: "9b129329f58692f6e6578329498a8fe9fbe98f090beb764ffbb8ee2eadd01dcd" url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.6.0" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + sha256: "9d0e3b9cb16542ad660daee871e726a10d13a93b7b5391677c3160e8f5e83935" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.2.3" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.1.13" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + sha256: "4dca4feb77dc3ec7f6e27e49c53241eb8217f55e4f9b12599a27f8903bca5682" url: "https://pub.dev" source: hosted - version: "1.1.11+1" + version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: "92b9910f66ed1057fd4da7b040ae7c74cafacf885bdc81be496928d5049b032d" url: "https://pub.dev" source: hosted - version: "2.2.0" - visibility_detector: + version: "2.4.3" + video_player: dependency: transitive description: - name: visibility_detector - sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + name: video_player + sha256: "07ae1e03f2d4c8e2e9a75ee678f90acbc4506d4458a9c628512d119a1eee5754" url: "https://pub.dev" source: hosted - version: "0.4.0+2" + version: "2.14.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: d27054dea34d748a44f06d433a57005d2aac69944485b0abbaed3303dbcfa3f1 + url: "https://pub.dev" + source: hosted + version: "2.12.2" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: "2fc56e537324a19eb649fca991aa308ac961b5406292876fa657b062de461fd8" + url: "https://pub.dev" + source: hosted + version: "2.12.0" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "92c0fbabe20c788e71fd10d26cea998d0d253282e65d145aed0818731cf593ce" + url: "https://pub.dev" + source: hosted + version: "6.9.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" + url: "https://pub.dev" + source: hosted + version: "2.4.0" vm_service: dependency: transitive description: name: vm_service - sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0" + url: "https://pub.dev" + source: hosted + version: "15.3.0" + vsc_quill_delta_to_html: + dependency: "direct main" + description: + name: vsc_quill_delta_to_html + sha256: "9aca60d53ed1b700e922dabff8cd8b3490daecbf99c258f19eb45820b794fa45" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + wakelock_plus: + dependency: transitive + description: + name: wakelock_plus + sha256: "9a91139ee876c24a9ebe1484e4b9b7923b07d368566a5e0b2301870b0f5029c8" + url: "https://pub.dev" + source: hosted + version: "1.8.1" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: "764c25504562abc8ac3406f5d175f126b276e6ba916c7c2675690b73368ca384" url: "https://pub.dev" source: hosted - version: "14.3.1" + version: "1.7.0" watcher: dependency: transitive description: name: watcher - sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.1" web: dependency: transitive description: name: web - sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "3.0.3" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: d53e1ccf5516f25017e3c9d44c39034db352d20fa34fe200674270242c2c5111 + url: "https://pub.dev" + source: hosted + version: "4.14.1" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "4de8b3d1ff4ebe1bdb42e68a5e4f809194a3cb0117a8f495f590004f00da3964" + url: "https://pub.dev" + source: hosted + version: "4.14.1" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" + url: "https://pub.dev" + source: hosted + version: "2.15.1" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: a9cc3f507ee40127ed0812ca54d00701a27833f51ea0b5820f4b3e7f42518bf3 + url: "https://pub.dev" + source: hosted + version: "3.27.0" win32: dependency: transitive description: name: win32 - sha256: e1d0cc62e65dc2561f5071fcbccecf58ff20c344f8f3dc7d4922df372a11df1f + sha256: a0b93865d5644f11cf6a8c3f6db909f1ec168958b5805f6cc684adea957cd63d url: "https://pub.dev" source: hosted - version: "5.7.1" + version: "6.4.0" + windows_file_picker: + dependency: transitive + description: + name: windows_file_picker + sha256: "9f3aa833068b09e380fdc59560ad260a4a14e9397173abb533699f967443602e" + url: "https://pub.dev" + source: hosted + version: "2.0.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" xml: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + sha256: "67f0aff7be013d107995e9b75bf4e7f2c3ef2dfdb2c8e68024bba0a7fd5756a4" url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "7.0.1" yaml: dependency: transitive description: name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + sha256: f67cdd8e07d3c6329146aaef1ba043542b3134c12489f553ca9a7435d1068aea url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.4" sdks: - dart: ">=3.10.0-0 <3.13.0-z" - flutter: ">=3.29.0" + dart: ">=3.13.0 <3.15.0-z" + flutter: ">=3.47.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8fa84e6b..1e4724f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,13 +35,13 @@ dependencies: shared_preferences: ^2.5.3 # imei_plugin: ^1.2.0 # flutter_flexible_toast: ^0.1.4 - fluttertoast: ^8.2.12 - local_auth: 2.1.8 - local_auth_android: ^1.0.48 + fluttertoast: ^10.0.0 + local_auth: ^3.0.2 + local_auth_android: ^2.2.0 http_interceptor: any # connectivity: ^3.0.6 - connectivity_plus: ^6.1.4 + connectivity_plus: ^7.3.1 maps_launcher: ^3.0.0+1 url_launcher: ^6.3.2 url_launcher_ios: ^6.3.2 @@ -54,7 +54,7 @@ dependencies: #Icons eva_icons_flutter: ^4.0.0 font_awesome_flutter: ^11.0.0 - dropdown_search: ^5.0.6 + dropdown_search: ^8.1.0 flutter_staggered_grid_view: ^0.7.0 expandable: ^5.0.1 @@ -62,7 +62,7 @@ dependencies: # Qr code Scanner barcode_scan2: ^4.5.1 # permissions - permission_handler: ^11.1.0 + permission_handler: ^13.0.2 # device_info: ^2.0.2 # The following adds the Cupertino Icons font to your application. @@ -74,14 +74,14 @@ dependencies: percent_indicator: ^4.2.3 #Dependency Injection - get_it: ^7.6.4 + get_it: ^9.3.0 #chart - fl_chart: ^0.65.0 + fl_chart: ^1.2.0 # Firebase - firebase_messaging: ^14.7.5 - firebase_analytics : ^10.7.1 + firebase_messaging: ^16.7.0 + firebase_analytics : ^12.6.0 # cloud_firestore: ^4.15.8 #GIF image @@ -91,17 +91,17 @@ dependencies: #Autocomplete TextField autocomplete_textfield: ^2.0.1 date_time_picker: ^2.0.0 - flutter_datetime_picker_plus: ^2.1.0 + flutter_datetime_picker_plus: ^3.0.1 # Html html: ^0.15.4 numberpicker: ^2.1.2 # Flutter Html View - flutter_html: ^3.0.0-beta.2 +# flutter_html: ^3.0.0-beta.2 sticky_headers: ^0.3.0+2 - file_picker: ^8.1.3 + file_picker: ^13.1.0 #speech to text # speech_to_text: @@ -114,20 +114,25 @@ dependencies: # Html Editor Enhanced #html_editor_enhanced: any - html_editor_enhanced: ^2.6.0 +# html_editor_enhanced: ^2.7.1 +# html_editor_plus: ^0.0.7 + flutter_quill: ^11.6.0 + flutter_quill_extensions: ^11.0.0 + flutter_quill_delta_from_html: ^1.5.3 + vsc_quill_delta_to_html: ^1.0.5 jhijri_picker: ^1.0.1 jhijri: ^1.0.0 #Network Image - cached_network_image: ^3.4.1 + cached_network_image: ^4.0.4 # Badges - badges: ^3.1.2 + badges: ^4.0.1 # Hijri # hijri: ^2.0.3 - hijri_picker: ^3.0.0 + hijri_picker: ^5.0.0 #flutter_datetime_picker: ^1.5.1 localization: ^2.1.1 @@ -136,16 +141,16 @@ dependencies: flutter_math_fork: ^0.7.2 # cloudflare_turnstile: ^3.0.1 - flutter_zoom_videosdk: 1.12.10 - dart_jsonwebtoken: ^2.14.0 - two_dimensional_scrollables: ^0.3.3 - timezone: ^0.10.1 + flutter_zoom_videosdk: ^2.5.10 + dart_jsonwebtoken: ^3.4.1 + two_dimensional_scrollables: ^0.5.5 + timezone: ^0.11.1 logger: ^2.6.1 freerasp: ^8.2.1 safe_device: ^1.4.1 path_provider: ^2.0.8 open_filex: ^4.7.0 - flutter_widget_from_html: ^0.17.1 + flutter_widget_from_html: ^0.17.4 dependency_overrides: @@ -155,6 +160,7 @@ dependency_overrides: flutter_plugin_android_lifecycle: 2.0.27 #hijri_picker: ^3.0.0 path_provider: ^2.1.5 +# permission_handler_android: 13.0.1 dev_dependencies: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index d552c6c7..94ed9fdb 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,26 +7,29 @@ #include "generated_plugin_registrant.h" #include +#include #include -#include #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); FirebaseCorePluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); - FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi")); LocalAuthPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("LocalAuthPlugin")); MapsLauncherPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("MapsLauncherPlugin")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + SpeechToTextWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SpeechToTextWindows")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 6c950ebb..5cddd8eb 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,15 +4,17 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus + file_selector_windows firebase_core - flutter_inappwebview_windows local_auth_windows maps_launcher permission_handler_windows + speech_to_text_windows url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES)