Merge branch 'development_v2.5' of https://gitlab.com/Cloud_Solution/diplomatic-quarter into fatima_v2
# Conflicts: # lib/widgets/input/text_field.dartmerge-requests/575/head
commit
7634c35e3d
@ -1,4 +1,27 @@
|
||||
-keep class tvi.webrtc.** { *; }
|
||||
-keep class com.twilio.video.** { *; }
|
||||
-keep class com.twilio.common.** { *; }
|
||||
-keepattributes InnerClasses
|
||||
-keepattributes InnerClasses
|
||||
|
||||
-keep class com.ejada.** { *; }
|
||||
-keep class org.webrtc.** { *; }
|
||||
|
||||
-ignorewarnings
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes Exceptions
|
||||
-keepattributes InnerClasses
|
||||
-keepattributes Signature
|
||||
-keep class com.hianalytics.android.**{*;}
|
||||
-keep class com.huawei.updatesdk.**{*;}
|
||||
-keep class com.huawei.hms.**{*;}
|
||||
|
||||
## Flutter wrapper
|
||||
-keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-dontwarn io.flutter.embedding.**
|
||||
-keep class com.huawei.hms.flutter.** { *; }
|
||||
-repackageclasses
|
||||
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* ---------------
|
||||
* Note: Todo
|
||||
* ---------------
|
||||
* Need to be place in huawei_push (package com.huawei.hms.flutter.push.hms) and define in huawei_push manifest.xml
|
||||
* */
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
|
||||
import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
|
||||
import com.huawei.hms.flutter.push.utils.ApplicationUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
//package com.huawei.hms.flutter.push.hms
|
||||
//
|
||||
//
|
||||
//import android.content.Context;
|
||||
//import android.content.Intent;
|
||||
//import android.content.SharedPreferences;
|
||||
//
|
||||
//import com.huawei.hms.flutter.push.hms.FlutterHmsMessageService;
|
||||
//import com.huawei.hms.flutter.push.utils.ApplicationUtils;
|
||||
//import com.huawei.hms.push.RemoteMessage;
|
||||
//
|
||||
//import org.json.JSONObject;
|
||||
//
|
||||
//public class CustomFlutterHmsMessageService extends FlutterHmsMessageService {
|
||||
// @Override
|
||||
// public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
// super.onMessageReceived(remoteMessage);
|
||||
// try {
|
||||
// String jsonStr = remoteMessage.getData();
|
||||
// JSONObject json_data = new JSONObject(jsonStr);
|
||||
// JSONObject json_data_data = new JSONObject(json_data.getString("data"));
|
||||
// if(json_data_data.getString("is_call").equalsIgnoreCase("true")){
|
||||
// boolean isApplicationInForeground = ApplicationUtils.isApplicationInForeground(this);
|
||||
// if(!isApplicationInForeground){
|
||||
// SharedPreferences preferences = getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE);
|
||||
// preferences.edit().putString("flutter.call_data", json_data.getString("data")).apply();
|
||||
//
|
||||
// Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
||||
// intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
// startActivity(intent);
|
||||
// Log.v("onMessageReceived", "startActivity(intent) called");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
@ -1,58 +1,58 @@
|
||||
package com.ejada.hmg.opentok
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import com.ejada.hmg.R
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import io.flutter.plugin.platform.PlatformView
|
||||
import io.flutter.plugin.platform.PlatformViewFactory
|
||||
|
||||
class LocalVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
|
||||
companion object {
|
||||
private lateinit var view: LocalVideoPlatformView
|
||||
|
||||
fun getViewInstance(context: Context): LocalVideoPlatformView {
|
||||
if(!this::view.isInitialized) {
|
||||
view = LocalVideoPlatformView(context)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
||||
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
return getViewInstance(context)
|
||||
}
|
||||
}
|
||||
|
||||
class LocalVideoPlatformView(context: Context) : PlatformView {
|
||||
private val videoContainer: LocalVideoContainer = LocalVideoContainer(context)
|
||||
|
||||
val container get() = videoContainer.publisherContainer
|
||||
|
||||
override fun getView(): View {
|
||||
return videoContainer
|
||||
}
|
||||
|
||||
override fun dispose() {}
|
||||
}
|
||||
|
||||
class LocalVideoContainer @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyle, defStyleRes) {
|
||||
|
||||
var publisherContainer: FrameLayout private set
|
||||
|
||||
init {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.local_video, this, true)
|
||||
publisherContainer = view.findViewById(R.id.publisher_container)
|
||||
}
|
||||
}
|
||||
//package com.ejada.hmg.opentok
|
||||
//
|
||||
//import android.content.Context
|
||||
//import android.util.AttributeSet
|
||||
//import android.view.LayoutInflater
|
||||
//import android.view.View
|
||||
//import android.widget.FrameLayout
|
||||
//import android.widget.LinearLayout
|
||||
//import com.ejada.hmg.R
|
||||
//import io.flutter.plugin.common.StandardMessageCodec
|
||||
//import io.flutter.plugin.platform.PlatformView
|
||||
//import io.flutter.plugin.platform.PlatformViewFactory
|
||||
//
|
||||
//class LocalVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
//
|
||||
// companion object {
|
||||
// private lateinit var view: LocalVideoPlatformView
|
||||
//
|
||||
// fun getViewInstance(context: Context): LocalVideoPlatformView {
|
||||
// if(!this::view.isInitialized) {
|
||||
// view = LocalVideoPlatformView(context)
|
||||
// }
|
||||
//
|
||||
// return view
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
// return getViewInstance(context)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//class LocalVideoPlatformView(context: Context) : PlatformView {
|
||||
// private val videoContainer: LocalVideoContainer = LocalVideoContainer(context)
|
||||
//
|
||||
// val container get() = videoContainer.publisherContainer
|
||||
//
|
||||
// override fun getView(): View {
|
||||
// return videoContainer
|
||||
// }
|
||||
//
|
||||
// override fun dispose() {}
|
||||
//}
|
||||
//
|
||||
//class LocalVideoContainer @JvmOverloads constructor(
|
||||
// context: Context,
|
||||
// attrs: AttributeSet? = null,
|
||||
// defStyle: Int = 0,
|
||||
// defStyleRes: Int = 0
|
||||
//) : LinearLayout(context, attrs, defStyle, defStyleRes) {
|
||||
//
|
||||
// var publisherContainer: FrameLayout private set
|
||||
//
|
||||
// init {
|
||||
// val view = LayoutInflater.from(context).inflate(R.layout.local_video, this, true)
|
||||
// publisherContainer = view.findViewById(R.id.publisher_container)
|
||||
// }
|
||||
//}
|
||||
@ -1,170 +1,170 @@
|
||||
package com.ejada.hmg.opentok
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import android.view.ViewGroup
|
||||
import com.facebook.stetho.urlconnection.StethoURLConnectionManager
|
||||
import com.opentok.android.*
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
|
||||
enum class OpenTokSDKState {
|
||||
LOGGED_OUT,
|
||||
LOGGED_IN,
|
||||
WAIT,
|
||||
ERROR
|
||||
}
|
||||
|
||||
class OpenTok(private var context: Context, private var flutterEngine: FlutterEngine){
|
||||
private lateinit var remoteVideoPlatformView: RemoteVideoPlatformView
|
||||
private lateinit var localVideoPlatformView: LocalVideoPlatformView
|
||||
|
||||
init {
|
||||
remoteVideoPlatformView = RemoteVideoFactory.getViewInstance(context)
|
||||
flutterEngine
|
||||
.platformViewsController
|
||||
.registry
|
||||
.registerViewFactory("remote-video-container", RemoteVideoFactory())
|
||||
|
||||
localVideoPlatformView = LocalVideoFactory.getViewInstance(context)
|
||||
flutterEngine
|
||||
.platformViewsController
|
||||
.registry
|
||||
.registerViewFactory("local-video-container", LocalVideoFactory())
|
||||
}
|
||||
|
||||
private var session: Session? = null
|
||||
private var publisher: Publisher? = null
|
||||
private var subscriber: Subscriber? = null
|
||||
|
||||
|
||||
|
||||
private val sessionListener: Session.SessionListener = object: Session.SessionListener {
|
||||
override fun onConnected(session: Session) {
|
||||
// Connected to session
|
||||
Log.d("MainActivity", "Connected to session ${session.sessionId}")
|
||||
|
||||
publisher = Publisher.Builder(context).build().apply {
|
||||
setPublisherListener(publisherListener)
|
||||
renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
|
||||
|
||||
view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
localVideoPlatformView.container.addView(view)
|
||||
}
|
||||
|
||||
notifyFlutter(OpenTokSDKState.LOGGED_IN)
|
||||
session.publish(publisher)
|
||||
}
|
||||
|
||||
override fun onDisconnected(session: Session) {
|
||||
notifyFlutter(OpenTokSDKState.LOGGED_OUT)
|
||||
}
|
||||
|
||||
override fun onStreamReceived(session: Session, stream: Stream) {
|
||||
Log.d(
|
||||
"MainActivity",
|
||||
"onStreamReceived: New Stream Received " + stream.streamId + " in session: " + session.sessionId
|
||||
)
|
||||
if (subscriber == null) {
|
||||
subscriber = Subscriber.Builder(context, stream).build().apply {
|
||||
renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
|
||||
setSubscriberListener(subscriberListener)
|
||||
session.subscribe(this)
|
||||
|
||||
remoteVideoPlatformView.container.addView(view)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStreamDropped(session: Session, stream: Stream) {
|
||||
Log.d(
|
||||
"MainActivity",
|
||||
"onStreamDropped: Stream Dropped: " + stream.streamId + " in session: " + session.sessionId
|
||||
)
|
||||
|
||||
if (subscriber != null) {
|
||||
subscriber = null
|
||||
|
||||
remoteVideoPlatformView.container.removeAllViews()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(session: Session, opentokError: OpentokError) {
|
||||
Log.d("MainActivity", "Session error: " + opentokError.message)
|
||||
notifyFlutter(OpenTokSDKState.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
private val publisherListener: PublisherKit.PublisherListener = object : PublisherKit.PublisherListener {
|
||||
override fun onStreamCreated(publisherKit: PublisherKit, stream: Stream) {
|
||||
Log.d("MainActivity", "onStreamCreated: Publisher Stream Created. Own stream " + stream.streamId)
|
||||
}
|
||||
|
||||
override fun onStreamDestroyed(publisherKit: PublisherKit, stream: Stream) {
|
||||
Log.d("MainActivity", "onStreamDestroyed: Publisher Stream Destroyed. Own stream " + stream.streamId)
|
||||
}
|
||||
|
||||
override fun onError(publisherKit: PublisherKit, opentokError: OpentokError) {
|
||||
Log.d("MainActivity", "PublisherKit onError: " + opentokError.message)
|
||||
notifyFlutter(OpenTokSDKState.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
var subscriberListener: SubscriberKit.SubscriberListener = object : SubscriberKit.SubscriberListener {
|
||||
override fun onConnected(subscriberKit: SubscriberKit) {
|
||||
Log.d("MainActivity", "onConnected: Subscriber connected. Stream: " + subscriberKit.stream.streamId)
|
||||
}
|
||||
|
||||
override fun onDisconnected(subscriberKit: SubscriberKit) {
|
||||
Log.d("MainActivity", "onDisconnected: Subscriber disconnected. Stream: " + subscriberKit.stream.streamId)
|
||||
notifyFlutter(OpenTokSDKState.LOGGED_OUT)
|
||||
}
|
||||
|
||||
override fun onError(subscriberKit: SubscriberKit, opentokError: OpentokError) {
|
||||
Log.d("MainActivity", "SubscriberKit onError: " + opentokError.message)
|
||||
notifyFlutter(OpenTokSDKState.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
fun initSession(call: MethodCall, result: MethodChannel.Result) {
|
||||
|
||||
val apiKey = requireNotNull(call.argument<String>("apiKey"))
|
||||
val sessionId = requireNotNull(call.argument<String>("sessionId"))
|
||||
val token = requireNotNull(call.argument<String>("token"))
|
||||
|
||||
notifyFlutter(OpenTokSDKState.WAIT)
|
||||
session = Session.Builder(context, apiKey, sessionId).build()
|
||||
session?.setSessionListener(sessionListener)
|
||||
session?.connect(token)
|
||||
result.success("")
|
||||
}
|
||||
|
||||
fun swapCamera(call: MethodCall, result: MethodChannel.Result) {
|
||||
publisher?.cycleCamera()
|
||||
result.success("")
|
||||
}
|
||||
|
||||
fun toggleAudio(call: MethodCall, result: MethodChannel.Result) {
|
||||
val publishAudio = requireNotNull(call.argument<Boolean>("publishAudio"))
|
||||
publisher?.publishAudio = publishAudio
|
||||
result.success("")
|
||||
}
|
||||
|
||||
fun toggleVideo(call: MethodCall, result: MethodChannel.Result) {
|
||||
val publishVideo = requireNotNull(call.argument<Boolean>("publishVideo"))
|
||||
publisher?.publishVideo = publishVideo
|
||||
result.success("")
|
||||
}
|
||||
|
||||
private fun notifyFlutter(state: OpenTokSDKState) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge")
|
||||
.invokeMethod("updateState", state.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
//package com.ejada.hmg.opentok
|
||||
//
|
||||
//import android.content.Context
|
||||
//import android.os.Handler
|
||||
//import android.os.Looper
|
||||
//import android.util.Log
|
||||
//import android.view.ViewGroup
|
||||
//import com.facebook.stetho.urlconnection.StethoURLConnectionManager
|
||||
//import com.opentok.android.*
|
||||
//import io.flutter.embedding.engine.FlutterEngine
|
||||
//import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister
|
||||
//import io.flutter.plugin.common.MethodCall
|
||||
//import io.flutter.plugin.common.MethodChannel
|
||||
//
|
||||
//
|
||||
//enum class OpenTokSDKState {
|
||||
// LOGGED_OUT,
|
||||
// LOGGED_IN,
|
||||
// WAIT,
|
||||
// ERROR
|
||||
//}
|
||||
//
|
||||
//class OpenTok(private var context: Context, private var flutterEngine: FlutterEngine){
|
||||
// private lateinit var remoteVideoPlatformView: RemoteVideoPlatformView
|
||||
// private lateinit var localVideoPlatformView: LocalVideoPlatformView
|
||||
//
|
||||
// init {
|
||||
// remoteVideoPlatformView = RemoteVideoFactory.getViewInstance(context)
|
||||
// flutterEngine
|
||||
// .platformViewsController
|
||||
// .registry
|
||||
// .registerViewFactory("remote-video-container", RemoteVideoFactory())
|
||||
//
|
||||
// localVideoPlatformView = LocalVideoFactory.getViewInstance(context)
|
||||
// flutterEngine
|
||||
// .platformViewsController
|
||||
// .registry
|
||||
// .registerViewFactory("local-video-container", LocalVideoFactory())
|
||||
// }
|
||||
//
|
||||
// private var session: Session? = null
|
||||
// private var publisher: Publisher? = null
|
||||
// private var subscriber: Subscriber? = null
|
||||
//
|
||||
//
|
||||
//
|
||||
// private val sessionListener: Session.SessionListener = object: Session.SessionListener {
|
||||
// override fun onConnected(session: Session) {
|
||||
// // Connected to session
|
||||
// Log.d("MainActivity", "Connected to session ${session.sessionId}")
|
||||
//
|
||||
// publisher = Publisher.Builder(context).build().apply {
|
||||
// setPublisherListener(publisherListener)
|
||||
// renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
|
||||
//
|
||||
// view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
// localVideoPlatformView.container.addView(view)
|
||||
// }
|
||||
//
|
||||
// notifyFlutter(OpenTokSDKState.LOGGED_IN)
|
||||
// session.publish(publisher)
|
||||
// }
|
||||
//
|
||||
// override fun onDisconnected(session: Session) {
|
||||
// notifyFlutter(OpenTokSDKState.LOGGED_OUT)
|
||||
// }
|
||||
//
|
||||
// override fun onStreamReceived(session: Session, stream: Stream) {
|
||||
// Log.d(
|
||||
// "MainActivity",
|
||||
// "onStreamReceived: New Stream Received " + stream.streamId + " in session: " + session.sessionId
|
||||
// )
|
||||
// if (subscriber == null) {
|
||||
// subscriber = Subscriber.Builder(context, stream).build().apply {
|
||||
// renderer?.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
|
||||
// setSubscriberListener(subscriberListener)
|
||||
// session.subscribe(this)
|
||||
//
|
||||
// remoteVideoPlatformView.container.addView(view)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onStreamDropped(session: Session, stream: Stream) {
|
||||
// Log.d(
|
||||
// "MainActivity",
|
||||
// "onStreamDropped: Stream Dropped: " + stream.streamId + " in session: " + session.sessionId
|
||||
// )
|
||||
//
|
||||
// if (subscriber != null) {
|
||||
// subscriber = null
|
||||
//
|
||||
// remoteVideoPlatformView.container.removeAllViews()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onError(session: Session, opentokError: OpentokError) {
|
||||
// Log.d("MainActivity", "Session error: " + opentokError.message)
|
||||
// notifyFlutter(OpenTokSDKState.ERROR)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private val publisherListener: PublisherKit.PublisherListener = object : PublisherKit.PublisherListener {
|
||||
// override fun onStreamCreated(publisherKit: PublisherKit, stream: Stream) {
|
||||
// Log.d("MainActivity", "onStreamCreated: Publisher Stream Created. Own stream " + stream.streamId)
|
||||
// }
|
||||
//
|
||||
// override fun onStreamDestroyed(publisherKit: PublisherKit, stream: Stream) {
|
||||
// Log.d("MainActivity", "onStreamDestroyed: Publisher Stream Destroyed. Own stream " + stream.streamId)
|
||||
// }
|
||||
//
|
||||
// override fun onError(publisherKit: PublisherKit, opentokError: OpentokError) {
|
||||
// Log.d("MainActivity", "PublisherKit onError: " + opentokError.message)
|
||||
// notifyFlutter(OpenTokSDKState.ERROR)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// var subscriberListener: SubscriberKit.SubscriberListener = object : SubscriberKit.SubscriberListener {
|
||||
// override fun onConnected(subscriberKit: SubscriberKit) {
|
||||
// Log.d("MainActivity", "onConnected: Subscriber connected. Stream: " + subscriberKit.stream.streamId)
|
||||
// }
|
||||
//
|
||||
// override fun onDisconnected(subscriberKit: SubscriberKit) {
|
||||
// Log.d("MainActivity", "onDisconnected: Subscriber disconnected. Stream: " + subscriberKit.stream.streamId)
|
||||
// notifyFlutter(OpenTokSDKState.LOGGED_OUT)
|
||||
// }
|
||||
//
|
||||
// override fun onError(subscriberKit: SubscriberKit, opentokError: OpentokError) {
|
||||
// Log.d("MainActivity", "SubscriberKit onError: " + opentokError.message)
|
||||
// notifyFlutter(OpenTokSDKState.ERROR)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fun initSession(call: MethodCall, result: MethodChannel.Result) {
|
||||
//
|
||||
// val apiKey = requireNotNull(call.argument<String>("apiKey"))
|
||||
// val sessionId = requireNotNull(call.argument<String>("sessionId"))
|
||||
// val token = requireNotNull(call.argument<String>("token"))
|
||||
//
|
||||
// notifyFlutter(OpenTokSDKState.WAIT)
|
||||
// session = Session.Builder(context, apiKey, sessionId).build()
|
||||
// session?.setSessionListener(sessionListener)
|
||||
// session?.connect(token)
|
||||
// result.success("")
|
||||
// }
|
||||
//
|
||||
// fun swapCamera(call: MethodCall, result: MethodChannel.Result) {
|
||||
// publisher?.cycleCamera()
|
||||
// result.success("")
|
||||
// }
|
||||
//
|
||||
// fun toggleAudio(call: MethodCall, result: MethodChannel.Result) {
|
||||
// val publishAudio = requireNotNull(call.argument<Boolean>("publishAudio"))
|
||||
// publisher?.publishAudio = publishAudio
|
||||
// result.success("")
|
||||
// }
|
||||
//
|
||||
// fun toggleVideo(call: MethodCall, result: MethodChannel.Result) {
|
||||
// val publishVideo = requireNotNull(call.argument<Boolean>("publishVideo"))
|
||||
// publisher?.publishVideo = publishVideo
|
||||
// result.success("")
|
||||
// }
|
||||
//
|
||||
// private fun notifyFlutter(state: OpenTokSDKState) {
|
||||
// Handler(Looper.getMainLooper()).post {
|
||||
// MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "OpenTok-Platform-Bridge")
|
||||
// .invokeMethod("updateState", state.toString())
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
@ -1,58 +1,58 @@
|
||||
package com.ejada.hmg.opentok
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import com.ejada.hmg.R
|
||||
import io.flutter.plugin.common.StandardMessageCodec
|
||||
import io.flutter.plugin.platform.PlatformView
|
||||
import io.flutter.plugin.platform.PlatformViewFactory
|
||||
|
||||
class RemoteVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
|
||||
companion object {
|
||||
private lateinit var view: RemoteVideoPlatformView
|
||||
|
||||
fun getViewInstance(context: Context): RemoteVideoPlatformView {
|
||||
if(!this::view.isInitialized) {
|
||||
view = RemoteVideoPlatformView(context)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
}
|
||||
|
||||
override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
return getViewInstance(context)
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteVideoPlatformView(context: Context) : PlatformView {
|
||||
private val videoContainer: RemoteVideoContainer = RemoteVideoContainer(context)
|
||||
|
||||
val container get() = videoContainer.subscriberContainer
|
||||
|
||||
override fun getView(): View {
|
||||
return videoContainer
|
||||
}
|
||||
|
||||
override fun dispose() {}
|
||||
}
|
||||
|
||||
class RemoteVideoContainer @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyle, defStyleRes) {
|
||||
|
||||
var subscriberContainer: FrameLayout private set
|
||||
|
||||
init {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.remote_video, this, true)
|
||||
subscriberContainer = view.findViewById(R.id.subscriber_container)
|
||||
}
|
||||
}
|
||||
//package com.ejada.hmg.opentok
|
||||
//
|
||||
//import android.content.Context
|
||||
//import android.util.AttributeSet
|
||||
//import android.view.LayoutInflater
|
||||
//import android.view.View
|
||||
//import android.widget.FrameLayout
|
||||
//import android.widget.LinearLayout
|
||||
//import com.ejada.hmg.R
|
||||
//import io.flutter.plugin.common.StandardMessageCodec
|
||||
//import io.flutter.plugin.platform.PlatformView
|
||||
//import io.flutter.plugin.platform.PlatformViewFactory
|
||||
//
|
||||
//class RemoteVideoFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
|
||||
//
|
||||
// companion object {
|
||||
// private lateinit var view: RemoteVideoPlatformView
|
||||
//
|
||||
// fun getViewInstance(context: Context): RemoteVideoPlatformView {
|
||||
// if(!this::view.isInitialized) {
|
||||
// view = RemoteVideoPlatformView(context)
|
||||
// }
|
||||
//
|
||||
// return view
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
|
||||
// return getViewInstance(context)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//class RemoteVideoPlatformView(context: Context) : PlatformView {
|
||||
// private val videoContainer: RemoteVideoContainer = RemoteVideoContainer(context)
|
||||
//
|
||||
// val container get() = videoContainer.subscriberContainer
|
||||
//
|
||||
// override fun getView(): View {
|
||||
// return videoContainer
|
||||
// }
|
||||
//
|
||||
// override fun dispose() {}
|
||||
//}
|
||||
//
|
||||
//class RemoteVideoContainer @JvmOverloads constructor(
|
||||
// context: Context,
|
||||
// attrs: AttributeSet? = null,
|
||||
// defStyle: Int = 0,
|
||||
// defStyleRes: Int = 0
|
||||
//) : LinearLayout(context, attrs, defStyle, defStyleRes) {
|
||||
//
|
||||
// var subscriberContainer: FrameLayout private set
|
||||
//
|
||||
// init {
|
||||
// val view = LayoutInflater.from(context).inflate(R.layout.remote_video, this, true)
|
||||
// subscriberContainer = view.findViewById(R.id.subscriber_container)
|
||||
// }
|
||||
//}
|
||||
@ -1,42 +1,42 @@
|
||||
package com.ejada.hmg.utils
|
||||
|
||||
import com.ejada.hmg.MainActivity
|
||||
import com.ejada.hmg.opentok.OpenTok
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
class OpenTokPlatformBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
|
||||
|
||||
private lateinit var channel: MethodChannel
|
||||
private lateinit var openTok: OpenTok
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL = "OpenTok-Platform-Bridge"
|
||||
}
|
||||
|
||||
fun create(){
|
||||
openTok = OpenTok(mainActivity, flutterEngine)
|
||||
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
|
||||
channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
|
||||
when (call.method) {
|
||||
"initSession" -> {
|
||||
openTok.initSession(call, result)
|
||||
}
|
||||
"swapCamera" -> {
|
||||
openTok.swapCamera(call, result)
|
||||
}
|
||||
"toggleAudio" -> {
|
||||
openTok.toggleAudio(call, result)
|
||||
}
|
||||
"toggleVideo" -> {
|
||||
openTok.toggleVideo(call, result)
|
||||
}
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//package com.ejada.hmg.utils
|
||||
//
|
||||
//import com.ejada.hmg.MainActivity
|
||||
//import com.ejada.hmg.opentok.OpenTok
|
||||
//import io.flutter.embedding.engine.FlutterEngine
|
||||
//import io.flutter.plugin.common.MethodCall
|
||||
//import io.flutter.plugin.common.MethodChannel
|
||||
//
|
||||
//class OpenTokPlatformBridge(private var flutterEngine: FlutterEngine, private var mainActivity: MainActivity) {
|
||||
//
|
||||
// private lateinit var channel: MethodChannel
|
||||
// private lateinit var openTok: OpenTok
|
||||
//
|
||||
// companion object {
|
||||
// private const val CHANNEL = "OpenTok-Platform-Bridge"
|
||||
// }
|
||||
//
|
||||
// fun create(){
|
||||
// openTok = OpenTok(mainActivity, flutterEngine)
|
||||
// channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
|
||||
// channel.setMethodCallHandler { call: MethodCall, result: MethodChannel.Result ->
|
||||
// when (call.method) {
|
||||
// "initSession" -> {
|
||||
// openTok.initSession(call, result)
|
||||
// }
|
||||
// "swapCamera" -> {
|
||||
// openTok.swapCamera(call, result)
|
||||
// }
|
||||
// "toggleAudio" -> {
|
||||
// openTok.toggleAudio(call, result)
|
||||
// }
|
||||
// "toggleVideo" -> {
|
||||
// openTok.toggleVideo(call, result)
|
||||
// }
|
||||
// else -> {
|
||||
// result.notImplemented()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48.615" height="48.48" viewBox="0 0 48.615 48.48">
|
||||
<g id="phone-call_1_" data-name="phone-call (1)" transform="translate(0 -0.584)">
|
||||
<g id="Group_8539" data-name="Group 8539" transform="translate(0 0.584)">
|
||||
<path id="Path_4999" data-name="Path 4999" d="M47.642,37.832l-6.627-6.6a3.364,3.364,0,0,0-4.715,0l-4.206,4.31a1.128,1.128,0,0,1-1.483,0A113.953,113.953,0,0,1,21.667,27.6a105.911,105.911,0,0,1-8.006-8.9,1.078,1.078,0,0,1,0-1.483l4.4-4.3a3.435,3.435,0,0,0,0-4.773L11.437,1.522a3.5,3.5,0,0,0-4.773,0L1.218,6.991s-.243.232-.324.324C-2.176,11,2.724,22.689,14.611,34.507c8.654,8.7,18.433,14.528,24.272,14.528a4.276,4.276,0,0,0,2.8-.568c.162-.116.614-.521.614-.521l5.341-5.364A3.385,3.385,0,0,0,47.642,37.832Z" transform="translate(0 -0.584)" fill="#5ab145"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 842 B |
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="35.547" height="48.48" viewBox="0 0 35.547 48.48">
|
||||
<path id="map" d="M22.773,1A17.773,17.773,0,0,0,5,18.773c0,9.388,15.834,29.245,16.513,30.1a1.616,1.616,0,0,0,2.521,0c.679-.856,16.513-20.714,16.513-30.1A17.773,17.773,0,0,0,22.773,1Zm0,22.621a6.463,6.463,0,1,1,6.463-6.463A6.463,6.463,0,0,1,22.773,23.621Z" transform="translate(-5 -1)" fill="#5ab145"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 409 B |
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48.248" height="48.48" viewBox="0 0 48.248 48.48">
|
||||
<path id="whatsapp" d="M41.468,7.045A24.029,24.029,0,0,0,3.658,36.031L.25,48.48l12.735-3.341a24,24,0,0,0,11.48,2.924h.01A24.033,24.033,0,0,0,41.468,7.045ZM24.475,44.006h-.008A19.942,19.942,0,0,1,14.3,41.223l-.729-.433L6.018,42.772,8.035,35.4l-.475-.755a19.967,19.967,0,1,1,16.915,9.357ZM35.427,29.052c-.6-.3-3.551-1.752-4.1-1.953s-.95-.3-1.35.3-1.55,1.953-1.9,2.353-.7.451-1.3.15a16.4,16.4,0,0,1-4.827-2.979,18.106,18.106,0,0,1-3.339-4.158c-.35-.6,0-.895.263-1.225a16.98,16.98,0,0,0,1.5-2.053,1.1,1.1,0,0,0-.05-1.052c-.15-.3-1.35-3.255-1.85-4.457-.488-1.17-.982-1.012-1.351-1.03-.35-.017-.75-.021-1.15-.021a2.2,2.2,0,0,0-1.6.751,6.732,6.732,0,0,0-2.1,5.007c0,2.955,2.151,5.809,2.451,6.209s4.233,6.464,10.254,9.063A34.358,34.358,0,0,0,28.4,35.224a8.229,8.229,0,0,0,3.781.238c1.153-.173,3.551-1.452,4.052-2.854a5.015,5.015,0,0,0,.35-2.855C36.428,29.5,36.027,29.352,35.427,29.052Zm0,0" transform="translate(-0.25)" fill="#5ab145" fill-rule="evenodd"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
File diff suppressed because it is too large
Load Diff
@ -1,216 +1,61 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/call_page.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../conference_button_bar.dart';
|
||||
|
||||
class CallHomePage extends StatefulWidget {
|
||||
final String receiverId;
|
||||
final String callerId;
|
||||
|
||||
const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CallHomePageState createState() => _CallHomePageState();
|
||||
}
|
||||
|
||||
class _CallHomePageState extends State<CallHomePage> {
|
||||
bool showNoise = false;
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
|
||||
final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
|
||||
//Stream to enable video
|
||||
MediaStream localMediaStream;
|
||||
MediaStream remoteMediaStream;
|
||||
Signaling signaling = Signaling()..init();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
startCall();
|
||||
}
|
||||
|
||||
startCall() async{
|
||||
await _localRenderer.initialize();
|
||||
await _remoteRenderer.initialize();
|
||||
final connected = await receivedCall();
|
||||
}
|
||||
|
||||
|
||||
Future<bool> receivedCall() async {
|
||||
//Stream local media
|
||||
localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
_localRenderer.srcObject = localMediaStream;
|
||||
|
||||
final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream, onRemoteMediaStream: (remoteMediaStream){
|
||||
this.remoteMediaStream = remoteMediaStream;
|
||||
_remoteRenderer.srcObject = remoteMediaStream;
|
||||
});
|
||||
|
||||
if(connected){
|
||||
signaling.signalR.listen(
|
||||
onAcceptCall: (arg0){
|
||||
print(arg0.toString());
|
||||
},
|
||||
onCandidate: (candidateJson){
|
||||
signaling.addCandidate(candidateJson);
|
||||
},
|
||||
onDeclineCall: (arg0,arg1){
|
||||
// _onHangup();
|
||||
},
|
||||
onHangupCall: (arg0){
|
||||
// _onHangup();
|
||||
},
|
||||
|
||||
onOffer: (offerSdp, callerUser) async{
|
||||
print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
await signaling.answerOffer(offerSdp);
|
||||
}
|
||||
);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_localRenderer?.dispose();
|
||||
_remoteRenderer?.dispose();
|
||||
_audioButton?.close();
|
||||
_videoButton?.close();
|
||||
localMediaStream?.dispose();
|
||||
remoteMediaStream?.dispose();
|
||||
_disposeStreamsAndSubscriptions();
|
||||
}
|
||||
|
||||
Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return WillPopScope(
|
||||
// onWillPop: () async => false,
|
||||
// child: Scaffold(
|
||||
// backgroundColor: Colors.black,
|
||||
// // body: ,
|
||||
// ),
|
||||
// );
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: showNoise ? _buildNoiseBox() : buildLayout(),
|
||||
);
|
||||
}
|
||||
|
||||
LayoutBuilder buildLayout() {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
children: [
|
||||
CamViewWidget(
|
||||
localRenderer: _localRenderer,
|
||||
remoteRenderer: _remoteRenderer,
|
||||
constraints: constraints,
|
||||
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
),
|
||||
ConferenceButtonBar(
|
||||
audioEnabled: _audioButton.stream,
|
||||
videoEnabled: _videoButton.stream,
|
||||
onAudioEnabled: _onAudioEnable,
|
||||
onVideoEnabled: _onVideoEnabled,
|
||||
onSwitchCamera: _onSwitchCamera,
|
||||
onHangup: _onHangup,
|
||||
onPersonAdd: () {},
|
||||
onPersonRemove: () {},
|
||||
onHeight: _onHeightBar,
|
||||
onShow: _onShowBar,
|
||||
onHide: _onHideBar,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
NoiseBox _buildNoiseBox() {
|
||||
return NoiseBox(
|
||||
density: NoiseBoxDensity.xLow,
|
||||
backgroundColor: Colors.grey.shade900,
|
||||
child: Center(
|
||||
child: Container(
|
||||
color: Colors.black54,
|
||||
width: double.infinity,
|
||||
height: 40,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Waiting for another participant to connect to the call...',
|
||||
key: Key('text-wait'),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Function _onAudioEnable() {
|
||||
final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
final mute = audioTrack.muted;
|
||||
Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
_audioButton.add(mute);
|
||||
}
|
||||
|
||||
Function _onVideoEnabled() {
|
||||
final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
bool videoEnabled = videoTrack.enabled;
|
||||
localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
_videoButton.add(!videoEnabled);
|
||||
}
|
||||
|
||||
Function _onSwitchCamera() {
|
||||
Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
void _onShowBar() {
|
||||
setState(() {
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(true);
|
||||
}
|
||||
|
||||
void _onHeightBar(double height) {
|
||||
_onButtonBarHeightStreamController.add(height);
|
||||
}
|
||||
|
||||
void _onHideBar() {
|
||||
setState(() {
|
||||
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(false);
|
||||
}
|
||||
|
||||
Future<void> _onHangup() async {
|
||||
signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
print('onHangup');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// import 'dart:async';
|
||||
//
|
||||
// import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
// import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter/services.dart';
|
||||
// // import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
//
|
||||
// import '../conference_button_bar.dart';
|
||||
//
|
||||
// class CallHomePage extends StatefulWidget {
|
||||
// final String receiverId;
|
||||
// final String callerId;
|
||||
//
|
||||
// const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// _CallHomePageState createState() => _CallHomePageState();
|
||||
// }
|
||||
//
|
||||
// class _CallHomePageState extends State<CallHomePage> {
|
||||
// bool showNoise = false;
|
||||
// // RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
// // RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
//
|
||||
// final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
// final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
// final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
//
|
||||
// //Stream to enable video
|
||||
// // MediaStream localMediaStream;
|
||||
// // MediaStream remoteMediaStream;
|
||||
// Signaling signaling = Signaling()..init();
|
||||
//
|
||||
// @override
|
||||
// void initState() {
|
||||
// // TODO: implement initState
|
||||
// super.initState();
|
||||
// startCall();
|
||||
// }
|
||||
//
|
||||
// startCall() async{
|
||||
// // await _localRenderer.initialize();
|
||||
// // await _remoteRenderer.initialize();
|
||||
// }
|
||||
//
|
||||
// Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
// if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
// if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// backgroundColor: Colors.white,
|
||||
// body: Container() //showNoise ? _buildNoiseBox() : buildLayout(),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
@ -0,0 +1,186 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:diplomaticquarterapp/pages/conference/web_rtc/widgets/cam_view_widget.dart';
|
||||
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
|
||||
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../conference_button_bar.dart';
|
||||
|
||||
class CallHomePage extends StatefulWidget {
|
||||
final String receiverId;
|
||||
final String callerId;
|
||||
|
||||
const CallHomePage({Key key, this.receiverId, this.callerId}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CallHomePageState createState() => _CallHomePageState();
|
||||
}
|
||||
|
||||
class _CallHomePageState extends State<CallHomePage> {
|
||||
bool showNoise = true;
|
||||
RTCVideoRenderer _localRenderer = RTCVideoRenderer();
|
||||
RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
|
||||
|
||||
final StreamController<bool> _audioButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _videoButton = StreamController<bool>.broadcast();
|
||||
final StreamController<bool> _onButtonBarVisibleStreamController = StreamController<bool>.broadcast();
|
||||
final StreamController<double> _onButtonBarHeightStreamController = StreamController<double>.broadcast();
|
||||
|
||||
//Stream to enable video
|
||||
MediaStream localMediaStream;
|
||||
MediaStream remoteMediaStream;
|
||||
Signaling signaling = Signaling()..init();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// TODO: implement initState
|
||||
super.initState();
|
||||
startCall();
|
||||
}
|
||||
|
||||
startCall() async{
|
||||
await _localRenderer.initialize();
|
||||
await _remoteRenderer.initialize();
|
||||
final connected = await receivedCall();
|
||||
}
|
||||
|
||||
|
||||
Future<bool> receivedCall() async {
|
||||
//Stream local media
|
||||
localMediaStream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
|
||||
_localRenderer.srcObject = localMediaStream;
|
||||
|
||||
final connected = await signaling.acceptCall(widget.callerId, widget.receiverId, localMediaStream: localMediaStream, onRemoteMediaStream: (remoteMediaStream){
|
||||
setState(() {
|
||||
this.remoteMediaStream = remoteMediaStream;
|
||||
_remoteRenderer.srcObject = remoteMediaStream;
|
||||
});
|
||||
});
|
||||
|
||||
if(connected){
|
||||
signaling.signalR.listen(
|
||||
onAcceptCall: (arg0){
|
||||
print(arg0.toString());
|
||||
},
|
||||
onCandidate: (candidateJson){
|
||||
signaling.addCandidate(candidateJson);
|
||||
},
|
||||
onDeclineCall: (arg0,arg1){
|
||||
// _onHangup();
|
||||
},
|
||||
onHangupCall: (arg0){
|
||||
// _onHangup();
|
||||
},
|
||||
|
||||
onOffer: (offerSdp, callerUser) async{
|
||||
print('${offerSdp.toString()} | ${callerUser.toString()}');
|
||||
await signaling.answerOffer(offerSdp);
|
||||
}
|
||||
);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_localRenderer?.dispose();
|
||||
_remoteRenderer?.dispose();
|
||||
_audioButton?.close();
|
||||
_videoButton?.close();
|
||||
localMediaStream?.dispose();
|
||||
remoteMediaStream?.dispose();
|
||||
_disposeStreamsAndSubscriptions();
|
||||
}
|
||||
|
||||
Future<void> _disposeStreamsAndSubscriptions() async {
|
||||
if (_onButtonBarVisibleStreamController != null) await _onButtonBarVisibleStreamController.close();
|
||||
if (_onButtonBarHeightStreamController != null) await _onButtonBarHeightStreamController.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: buildLayout(),
|
||||
);
|
||||
}
|
||||
|
||||
LayoutBuilder buildLayout() {
|
||||
return LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
children: [
|
||||
CamViewWidget(
|
||||
localRenderer: _localRenderer,
|
||||
remoteRenderer: _remoteRenderer,
|
||||
constraints: constraints,
|
||||
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
|
||||
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
|
||||
),
|
||||
ConferenceButtonBar(
|
||||
audioEnabled: _audioButton.stream,
|
||||
videoEnabled: _videoButton.stream,
|
||||
onAudioEnabled: _onAudioEnable,
|
||||
onVideoEnabled: _onVideoEnabled,
|
||||
onSwitchCamera: _onSwitchCamera,
|
||||
onHangup: _onHangup,
|
||||
onPersonAdd: () {},
|
||||
onPersonRemove: () {},
|
||||
onHeight: _onHeightBar,
|
||||
onShow: _onShowBar,
|
||||
onHide: _onHideBar,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Function _onAudioEnable() {
|
||||
final audioTrack = localMediaStream.getAudioTracks()[0];
|
||||
final mute = audioTrack.muted;
|
||||
Helper.setMicrophoneMute(!mute, audioTrack);
|
||||
_audioButton.add(mute);
|
||||
}
|
||||
|
||||
Function _onVideoEnabled() {
|
||||
final videoTrack = localMediaStream.getVideoTracks()[0];
|
||||
bool videoEnabled = videoTrack.enabled;
|
||||
localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
|
||||
_videoButton.add(!videoEnabled);
|
||||
}
|
||||
|
||||
Function _onSwitchCamera() {
|
||||
Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
|
||||
}
|
||||
|
||||
void _onShowBar() {
|
||||
setState(() {
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(true);
|
||||
}
|
||||
|
||||
void _onHeightBar(double height) {
|
||||
_onButtonBarHeightStreamController.add(height);
|
||||
}
|
||||
|
||||
void _onHideBar() {
|
||||
setState(() {
|
||||
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
|
||||
});
|
||||
_onButtonBarVisibleStreamController.add(false);
|
||||
}
|
||||
|
||||
Future<void> _onHangup() async {
|
||||
signaling.hangupCall(widget.callerId, widget.receiverId);
|
||||
print('onHangup');
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,258 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
|
||||
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:maps_launcher/maps_launcher.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:map_launcher/map_launcher.dart';
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
class pharmacyContactsPage extends StatefulWidget {
|
||||
@override
|
||||
_pharmacyContactsPageState createState() => _pharmacyContactsPageState();
|
||||
}
|
||||
|
||||
class _pharmacyContactsPageState extends State<pharmacyContactsPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final latitude = "24.704016";
|
||||
final longitude = "46.676691";
|
||||
final phone = "+966112833400";
|
||||
final whatsApp = "+966558434444";
|
||||
final whatappURL_android = "whatsapp://send?phone=" + whatsApp;
|
||||
final whatappURL_ios = "https://wa.me/$whatsApp";
|
||||
final locationDescription = "Main Pharmacy OLAYA";
|
||||
|
||||
return AppScaffold(
|
||||
appBarTitle: TranslationBase.of(context).contactUs,
|
||||
isShowAppBar: true,
|
||||
isShowDecPage: false,
|
||||
isPharmacy: true,
|
||||
showPharmacyCart: false,
|
||||
showHomeAppBarIcon: false,
|
||||
isMainPharmacyPages: true,
|
||||
isBottomBar: true,
|
||||
body: Column(
|
||||
children: [
|
||||
Card(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(color: Colors.grey[300], width: 2),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 8,
|
||||
),
|
||||
child: Container(
|
||||
margin: EdgeInsets.all(10),
|
||||
padding: EdgeInsets.fromLTRB(5, 15, 5, 15),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(15),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
child: Text(TranslationBase.of(context).contactUsTime,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 35,
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
launch("tel://" + phone);
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/pharmacy/call.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Text(TranslationBase.of(context).phone,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
Text("+966 " + " -11- 2833400",
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
// launch('whatsapp://send?phone='+whatsApp);
|
||||
openWhatsApp();
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/pharmacy/whatsapp.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Text(TranslationBase.of(context).whatsApp,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
SizedBox(
|
||||
width: 30,
|
||||
),
|
||||
Text("+966 " + " 558434444",
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(5.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
InkWell(
|
||||
onTap: () {
|
||||
if (Platform.isIOS) { MapLauncher.showMarker(
|
||||
mapType: MapType.apple,
|
||||
coords: Coords(double.parse(latitude),
|
||||
double.parse(longitude)),
|
||||
title: locationDescription,);
|
||||
} else { MapLauncher.showMarker(
|
||||
mapType: MapType.google,
|
||||
coords: Coords(double.parse(latitude),
|
||||
double.parse(longitude)),
|
||||
title: locationDescription,
|
||||
// description: location.locationName,
|
||||
); }
|
||||
// MapsLauncher.launchCoordinates(double.parse(previousModel.productLocationService[index].latitude), double.parse(previousModel.productLocationService[index].longitude), previousModel.productLocationService[index].locationDescription);
|
||||
},
|
||||
// MapsLauncher.launchCoordinates(
|
||||
// double.parse(latitude),
|
||||
// double.parse(longitude));
|
||||
// },
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/pharmacy/location.svg',
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
TranslationBase.of(context).contactUsLocation,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[700],
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
letterSpacing: -0.68)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 50,
|
||||
),
|
||||
Center(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
IconButton(
|
||||
icon: new Image.asset(
|
||||
'assets/images/new-design/facebook.png'),
|
||||
tooltip: 'facebook',
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
launch("https://facebook.com/HMG.pharmacy");
|
||||
// launch("https://www.facebook.com/DrSulaimanAlHabib?ref=tn_tnmn");
|
||||
});
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: new Image.asset(
|
||||
'assets/images/new-design/twitter.png'),
|
||||
tooltip: 'Twitter',
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
launch("https://twitter.com/HMG_pharmacy");
|
||||
});
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: new Image.asset(
|
||||
'assets/images/pharmacy/instagram.png'),
|
||||
tooltip: 'Instagram',
|
||||
iconSize: 48,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
launch("https://instagram.com/HMG_pharmacy");
|
||||
});
|
||||
},
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
openWhatsApp() async {
|
||||
// bool Platform.isIOS = Theme.of(context).platform == TargetPlatform.iOS;
|
||||
var whatsapp = "+966558434444";
|
||||
var whatsappURL_android = "whatsapp://send?phone=" + whatsapp;
|
||||
var whatappURL_ios = "https://wa.me/$whatsapp";
|
||||
if (Platform.isIOS) {
|
||||
// for iOS phone only
|
||||
// if (await canLaunch(whatappURL_ios)) {
|
||||
await launch(whatappURL_ios, forceSafariVC: false);
|
||||
// } else {}
|
||||
} else {
|
||||
// android
|
||||
// if (await canLaunch(whatsappURL_android)) {
|
||||
await launch(whatsappURL_android);
|
||||
// } else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart';
|
||||
import 'package:diplomaticquarterapp/widgets/dialogs/confirm_dialog.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'PlatformBridge.dart';
|
||||
|
||||
class AppPermission{
|
||||
|
||||
|
||||
static Future<bool> askVideoCallPermission(BuildContext context) async {
|
||||
if (!(await Permission.camera.request().isGranted) || !(await Permission.microphone.request().isGranted)) {
|
||||
return false;
|
||||
}
|
||||
if (Platform.isAndroid && !(await PlatformBridge.shared().isDrawOverAppsPermissionAllowed())) {
|
||||
await _drawOverAppsMessageDialog(context);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Future _drawOverAppsMessageDialog(BuildContext context) async {
|
||||
ConfirmDialog dialog = new ConfirmDialog(
|
||||
context: context,
|
||||
confirmMessage: "Please select 'Dr. Alh'abib' from the list and allow draw over app permission to use live care.",
|
||||
okText: TranslationBase.of(context).confirm,
|
||||
cancelText: TranslationBase.of(context).cancel_nocaps,
|
||||
okFunction: () async {
|
||||
await PlatformBridge.shared().askDrawOverAppsPermission();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
cancelFunction: () => {});
|
||||
dialog.showAlertDialog(context);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue