diff --git a/android/CustomFlutterFirebaseMessagingService.java b/android/CustomFlutterFirebaseMessagingService.java
index 0a4d83be..113f256f 100644
--- a/android/CustomFlutterFirebaseMessagingService.java
+++ b/android/CustomFlutterFirebaseMessagingService.java
@@ -2,14 +2,33 @@ package io.flutter.plugins.firebasemessaging;
import android.content.Intent;
+import java.util.concurrent.TimeUnit;
+
import com.google.firebase.messaging.RemoteMessage;
+//public class CustomFlutterFirebaseMessagingService extends FlutterFirebaseMessagingService {
+// @Override
+// public void onMessageReceived(RemoteMessage remoteMessage) {
+// if (remoteMessage.getData().containsKey("is_call")) {
+// Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
+// startActivity(intent);
+// super.onMessageReceived(remoteMessage);
+// } else
+// super.onMessageReceived(remoteMessage);
+// }
+//}
+
public class CustomFlutterFirebaseMessagingService extends FlutterFirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData().containsKey("is_call")) {
Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
+ intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
+ try {
+ TimeUnit.SECONDS.sleep(5);
+ } catch (Exception e) {
+ }
super.onMessageReceived(remoteMessage);
} else
super.onMessageReceived(remoteMessage);
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index eb397698..8aa7ad73 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -13,6 +13,7 @@
+
@@ -30,7 +31,7 @@
-
+
@@ -42,6 +43,8 @@
android:name=".Application"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"
+ android:showOnLockScreen="true"
+ android:screenOrientation="sensorPortrait"
android:label="Dr. Alhabib">
if (methodCall.method == HMG_INTERNET_WIFI_CONNECT_METHOD) {
- connectHMGInternetWifi(methodCall,result)
-
- }else if (methodCall.method == HMG_GUEST_WIFI_CONNECT_METHOD) {
- connectHMGGuestWifi(methodCall,result)
-
- }else if (methodCall.method == ENABLE_WIFI_IF_NOT) {
- enableWifiIfNot(methodCall,result)
- }else if (methodCall.method == REGISTER_HMG_GEOFENCES) {
- registerHmgGeofences(methodCall,result)
- }else if (methodCall.method == UN_REGISTER_HMG_GEOFENCES) {
- unRegisterHmgGeofences(methodCall,result)
- }else{
-
+ connectHMGInternetWifi(methodCall, result)
+
+ } else if (methodCall.method == HMG_GUEST_WIFI_CONNECT_METHOD) {
+ connectHMGGuestWifi(methodCall, result)
+
+ } else if (methodCall.method == ENABLE_WIFI_IF_NOT) {
+ enableWifiIfNot(methodCall, result)
+ } else if (methodCall.method == REGISTER_HMG_GEOFENCES) {
+ registerHmgGeofences(methodCall, result)
+ } else if (methodCall.method == UN_REGISTER_HMG_GEOFENCES) {
+ unRegisterHmgGeofences(methodCall, result)
+ } else if (methodCall.method == IS_DRAW_OVER_APPS_PERMISSION_ALLOWED) {
+ isDrawOverAppsPermissionAllowed(methodCall, result)
+ } else if (methodCall.method == ASK_DRAW_OVER_APPS_PERMISSION) {
+ askDrawOverAppsPermission(methodCall, result)
+ } else if (methodCall.method == GET_INTENT) {
+ getIntentData(methodCall, result)
+ } else {
result.notImplemented()
}
}
- val res = channel.invokeMethod("localizedValue","errorConnectingHmgNetwork")
+ val res = channel.invokeMethod("localizedValue", "errorConnectingHmgNetwork")
}
- private fun connectHMGInternetWifi(methodCall: MethodCall, result: MethodChannel.Result){
+ private fun connectHMGInternetWifi(methodCall: MethodCall, result: MethodChannel.Result) {
(methodCall.arguments as ArrayList<*>).let {
- require(it.size > 0 && (it[0] is String),lazyMessage = {
+ require(it.size > 0 && (it[0] is String), lazyMessage = {
"Missing or invalid arguments (Must have one argument 'String at 0'"
})
val patientId = it[0].toString()
HMG_Internet(mainActivity)
- .connectToHMGGuestNetwork(patientId){ status, message ->
+ .connectToHMGGuestNetwork(patientId) { status, message ->
mainActivity.runOnUiThread {
- result.success(if(status) 1 else 0)
+ result.success(if (status) 1 else 0)
HMGUtils.popFlutterText(mainActivity, message)
Log.v(this.javaClass.simpleName, "$status | $message")
@@ -76,10 +92,10 @@ class PlatformBridge(private var flutterEngine: FlutterEngine, private var mainA
}
- private fun connectHMGGuestWifi(methodCall: MethodCall, result: MethodChannel.Result){
+ private fun connectHMGGuestWifi(methodCall: MethodCall, result: MethodChannel.Result) {
HMG_Guest(mainActivity).connectToHMGGuestNetwork { status, message ->
mainActivity.runOnUiThread {
- result.success(if(status) 1 else 0)
+ result.success(if (status) 1 else 0)
HMGUtils.popFlutterText(mainActivity, message)
Log.v(this.javaClass.simpleName, "$status | $message")
@@ -89,38 +105,76 @@ class PlatformBridge(private var flutterEngine: FlutterEngine, private var mainA
private fun enableWifiIfNot(methodCall: MethodCall, result: MethodChannel.Result) {
val wm = mainActivity.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager?
- if (wm != null){
+ if (wm != null) {
if (!wm.isWifiEnabled)
wm.isWifiEnabled = true
result.success(true)
- }else
- result.error("101","Error while opening wifi, Please try to open wifi yourself and try again","'WifiManager' service failed");
+ } else
+ result.error("101", "Error while opening wifi, Please try to open wifi yourself and try again", "'WifiManager' service failed");
}
private fun registerHmgGeofences(methodCall: MethodCall, result: MethodChannel.Result) {
- channel.invokeMethod("getGeoZones",null, object : MethodChannel.Result{
+ channel.invokeMethod("getGeoZones", null, object : MethodChannel.Result {
override fun success(result: Any?) {
- if(result is String) {
+ if (result is String) {
val geoZones = GeoZoneModel().listFrom(result)
- HMG_Geofence.shared(mainActivity).register(){ s, e -> }
+ HMG_Geofence.shared(mainActivity).register() { s, e -> }
}
}
- override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) { }
- override fun notImplemented() { }
+ override fun error(errorCode: String?, errorMessage: String?, errorDetails: Any?) {}
+ override fun notImplemented() {}
})
}
-
+
private fun unRegisterHmgGeofences(methodCall: MethodCall, result: MethodChannel.Result) {
HMG_Geofence.shared(mainActivity).unRegisterAll { status, exception ->
- if(status)
+ if (status)
result.success(true)
else
result.error("101", exception?.localizedMessage, exception);
}
}
-
+
+ private fun isDrawOverAppsPermissionAllowed(methodCall: MethodCall, result: MethodChannel.Result) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (
+ Settings.canDrawOverlays(mainActivity)
+ ) {
+ result.success(true)
+ } else {
+ result.success(false)
+ }
+ } else {
+ result.success(false)
+ }
+ }
+
+ private fun askDrawOverAppsPermission(methodCall: MethodCall, result: MethodChannel.Result) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
+ val uri = Uri.parse("package:" + mainActivity.getPackageName())
+ intent.setData(uri)
+ startActivityForResult(mainActivity, intent, 102, null)
+ result.success(true)
+ } else {
+ result.success(false)
+ }
+ }
+
+ private fun getIntentData(methodCall: MethodCall, result: MethodChannel.Result) {
+
+ val bundle: Bundle? = getIntent("").extras
+ if (bundle != null) {
+ val message = bundle.getString("notification") // 1
+ System.out.println("BundleExtra:" + message)
+ Toast.makeText(this.mainActivity, message + "", Toast.LENGTH_SHORT).show()
+ } else {
+ Toast.makeText(this.mainActivity, "Bundle Null", Toast.LENGTH_SHORT).show();
+ }
+ result.success(true);
+ }
}
diff --git a/ios/Flutter/.last_build_id b/ios/Flutter/.last_build_id
index 53427e0c..b3315e38 100644
--- a/ios/Flutter/.last_build_id
+++ b/ios/Flutter/.last_build_id
@@ -1 +1 @@
-3f8c659591fcdd0e47e3895f74af395c
\ No newline at end of file
+8d8845c5c035b7f87f2849054cdedb69
\ No newline at end of file
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 6c02c983..9bf7caa5 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -520,7 +520,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.hmg.smartphone;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
@@ -659,7 +659,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.hmg.smartphone;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -692,7 +692,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
- PRODUCT_BUNDLE_IDENTIFIER = com.hmg.smartphone;
+ PRODUCT_BUNDLE_IDENTIFIER = "com.HMG.HMG-Smartphone";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
diff --git a/lib/core/model/packages_offers/requests/CreateCustomerRequestModel.dart b/lib/core/model/packages_offers/requests/CreateCustomerRequestModel.dart
index 9cc3d3b9..d5022f0f 100644
--- a/lib/core/model/packages_offers/requests/CreateCustomerRequestModel.dart
+++ b/lib/core/model/packages_offers/requests/CreateCustomerRequestModel.dart
@@ -1,4 +1,5 @@
import 'package:diplomaticquarterapp/models/Authentication/authenticated_user.dart';
+import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
import 'package:flutter/cupertino.dart';
class PackagesCustomerRequestModel {
@@ -19,7 +20,9 @@ class PackagesCustomerRequestModel {
this.email = user.emailAddress;
this.phone = user.mobileNumber;
this.national_id = user.patientIdentificationNo;
- this.date_of_birth = user.dateofBirth;
+
+ String isoDateTime = DateUtil.getISODateFormat(user.dateofBirthDataTime);
+ this.date_of_birth = isoDateTime;
}
Map json() {
diff --git a/lib/core/model/packages_offers/responses/tamara_payment_option.dart b/lib/core/model/packages_offers/responses/tamara_payment_option.dart
index ad79f5f3..2b694a23 100644
--- a/lib/core/model/packages_offers/responses/tamara_payment_option.dart
+++ b/lib/core/model/packages_offers/responses/tamara_payment_option.dart
@@ -3,6 +3,7 @@ class TamaraPaymentOption {
double minLimit;
double maxLimit;
int id;
+ bool enable = true;
String fullName() => '$name Months';
diff --git a/lib/core/service/packages_offers/PackagesOffersServices.dart b/lib/core/service/packages_offers/PackagesOffersServices.dart
index ae5396a7..6c4e0d24 100644
--- a/lib/core/service/packages_offers/PackagesOffersServices.dart
+++ b/lib/core/service/packages_offers/PackagesOffersServices.dart
@@ -75,6 +75,7 @@ class OffersAndPackagesServices extends BaseService {
Future> getTamaraOptions({@required BuildContext context, @required bool showLoading = true}) async {
if (tamaraPaymentOptions != null && tamaraPaymentOptions.isNotEmpty) return tamaraPaymentOptions;
+ tamaraPaymentOptions.clear();
var url = EXA_CART_API_BASE_URL + PACKAGES_TAMARA_OPT;
await baseAppClient.simpleGet(url, headers: packagesAuthHeader, onSuccess: (dynamic stringResponse, int statusCode) {
if (statusCode == 200) {
diff --git a/lib/core/service/pharmacy_categorise_service.dart b/lib/core/service/pharmacy_categorise_service.dart
index be376c91..280022e0 100644
--- a/lib/core/service/pharmacy_categorise_service.dart
+++ b/lib/core/service/pharmacy_categorise_service.dart
@@ -5,6 +5,7 @@ import 'package:diplomaticquarterapp/core/model/pharmacy/categorise_parent_model
import 'package:diplomaticquarterapp/core/model/pharmacy/final_products_model.dart';
import 'package:diplomaticquarterapp/core/model/pharmacy/pharmacy_categorise.dart';
import 'package:diplomaticquarterapp/core/model/pharmacy/scan_qr_model.dart';
+import 'package:diplomaticquarterapp/models/LiveCare/validators.dart';
import 'base_service.dart';
@@ -303,9 +304,9 @@ class PharmacyCategoriseService extends BaseService {
_parentProductsList.clear();
endPoint = FILTERED_PRODUCTS +
"$categoryId" +
- "&manufacturerids=$brandId" +
- "&price_min=$min" +
- "&price_max=$max&page=1&limit=50";
+ "$brandId" +
+ "$min" +
+ "$max&page=1&limit=50";
await baseAppClient.getPharmacy(
endPoint,
onSuccess: (dynamic response, int statusCode) {
@@ -328,9 +329,9 @@ class PharmacyCategoriseService extends BaseService {
_subProductsList.clear();
endPoint = FILTERED_PRODUCTS +
"$categoryId" +
- "&manufacturerids=$brandId" +
- "&price_min=$min" +
- "&price_max=$max&page=1&limit=50";
+ "$brandId" +
+ "$min" +
+ "$max&page=1&limit=50";
await baseAppClient.getPharmacy(
endPoint,
onSuccess: (dynamic response, int statusCode) {
diff --git a/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart b/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart
index af750eab..b1fcc1d1 100644
--- a/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart
+++ b/lib/core/viewModels/packages_offers/PackagesOffersViewModel.dart
@@ -2,6 +2,7 @@ import 'package:diplomaticquarterapp/core/model/hospitals/hospitals_model.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCartItemsResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesCategoriesResponseModel.dart';
import 'package:diplomaticquarterapp/core/model/packages_offers/responses/PackagesResponseModel.dart';
+import 'package:diplomaticquarterapp/core/model/packages_offers/responses/tamara_payment_option.dart';
import 'package:diplomaticquarterapp/core/service/packages_offers/PackagesOffersServices.dart';
import 'package:diplomaticquarterapp/core/viewModels/base_view_model.dart';
import 'package:diplomaticquarterapp/locator.dart';
@@ -25,6 +26,22 @@ class PackagesViewModel extends BaseViewModel {
List get cartItemList => service.cartItemList;
List get hospitals => service.hospitals;
+ List get tamara_options => service.tamaraPaymentOptions;
+ bool allowTamara = true;
+
+ setTamaraIllegablity(double amount){
+ bool illegible = true;
+ if(tamara_options == null || tamara_options.isEmpty)
+ illegible = false;
+ else{
+ tamara_options.forEach((element) {
+ final ill = (amount >= element.minLimit && amount <= element.maxLimit);
+ element.enable = ill;
+ illegible = illegible || ill;
+ });
+ }
+ allowTamara = illegible;
+ }
String _cartItemCount = "";
diff --git a/lib/main.dart b/lib/main.dart
index 0dd18a2d..93af691e 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -168,7 +168,8 @@ class _MyApp extends State {
// ),
// ),
// ),
- initialRoute: SPLASH,
+ // initialRoute: SPLASH,
+ initialRoute: CALL_PAGE,
// initialRoute: OPENTOK_CALL_PAGE,
// initialRoute: PACKAGES_OFFERS,
// initialRoute: PACKAGES_ORDER_COMPLETED,
diff --git a/lib/pages/BookAppointment/BookConfirm.dart b/lib/pages/BookAppointment/BookConfirm.dart
index bdf387d6..7377bcc2 100644
--- a/lib/pages/BookAppointment/BookConfirm.dart
+++ b/lib/pages/BookAppointment/BookConfirm.dart
@@ -9,6 +9,7 @@ import 'package:diplomaticquarterapp/routes.dart';
import 'package:diplomaticquarterapp/services/appointment_services/GetDoctorsList.dart';
import 'package:diplomaticquarterapp/services/clinic_services/get_clinic_service.dart';
import 'package:diplomaticquarterapp/theme/colors.dart';
+import 'package:diplomaticquarterapp/uitl/PlatformBridge.dart';
import 'package:diplomaticquarterapp/uitl/app_shared_preferences.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/date_uitl.dart';
@@ -21,6 +22,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
+import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'book_reminder_page.dart';
@@ -240,6 +242,44 @@ class _BookConfirmState extends State {
);
}
+ Future askVideoCallPermission() async {
+ if (!(await Permission.camera.request().isGranted) || !(await Permission.microphone.request().isGranted)) {
+ return false;
+ }
+ if (!(await PlatformBridge.shared().isDrawOverAppsPermissionAllowed())) {
+ await drawOverAppsMessageDialog(context);
+ return false;
+ }
+ return true;
+ }
+
+ Future drawOverAppsMessageDialog(BuildContext context) async {
+ await showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ content: Text("Please select 'Diplomatic Quarter' from the list and allow draw over app permission to use live care."),
+ contentPadding: EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 0.0),
+ actions: [
+ FlatButton(
+ child: Text("Cancel"),
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ ),
+ FlatButton(
+ child: Text("Go to Settings"),
+ onPressed: () async {
+ await PlatformBridge.shared().askDrawOverAppsPermission();
+ Navigator.pop(context);
+ },
+ )
+ ],
+ );
+ },
+ );
+ }
+
cancelAppointment(DoctorList docObject, AppoitmentAllHistoryResultList appo, BuildContext context) {
ConfirmDialog.closeAlertDialog(context);
GifLoaderDialogUtils.showMyDialog(context);
diff --git a/lib/pages/conference/conference_page.dart b/lib/pages/conference/conference_page.dart
index dc00bf6e..c30e7cdf 100644
--- a/lib/pages/conference/conference_page.dart
+++ b/lib/pages/conference/conference_page.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:diplomaticquarterapp/models/LiveCare/room_model.dart';
import 'package:diplomaticquarterapp/pages/conference/conference_button_bar.dart';
import 'package:diplomaticquarterapp/pages/conference/conference_room.dart';
+import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/pages/conference/draggable_publisher.dart';
import 'package:diplomaticquarterapp/pages/conference/participant_widget.dart';
import 'package:diplomaticquarterapp/pages/conference/widgets/noise_box.dart';
@@ -152,6 +153,7 @@ class _ConferencePageState extends State {
Future _onHangup() async {
print('onHangup');
await _conferenceRoom.disconnect();
+ LandingPage.isOpenCallPage = false;
Navigator.of(context).pop();
}
diff --git a/lib/pages/conference/web_rtc/call_home_page.dart b/lib/pages/conference/web_rtc/call_home_page.dart
index 7153bf92..892871cc 100644
--- a/lib/pages/conference/web_rtc/call_home_page.dart
+++ b/lib/pages/conference/web_rtc/call_home_page.dart
@@ -2,6 +2,9 @@ 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';
@@ -9,6 +12,11 @@ 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();
}
@@ -24,33 +32,68 @@ class _CallHomePageState extends State {
final StreamController _onButtonBarHeightStreamController = StreamController.broadcast();
//Stream to enable video
- MediaStream stream;
+ MediaStream localMediaStream;
+ MediaStream remoteMediaStream;
+ Signaling signaling = Signaling()..init();
@override
void initState() {
// TODO: implement initState
super.initState();
- _localRenderer.initialize();
- _remoteRenderer.initialize();
+ startCall();
+ }
- enableVideo();
+ startCall() async{
+ await _localRenderer.initialize();
+ await _remoteRenderer.initialize();
+ final connected = await receivedCall();
}
- enableVideo() async {
- //Stream to enable video
- stream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': true});
- // _audioButton.add(false);
+
+ Future 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();
- stream.dispose();
+ _localRenderer?.dispose();
+ _remoteRenderer?.dispose();
+ _audioButton?.close();
+ _videoButton?.close();
+ localMediaStream?.dispose();
+ remoteMediaStream?.dispose();
_disposeStreamsAndSubscriptions();
}
@@ -83,7 +126,6 @@ class _CallHomePageState extends State {
CamViewWidget(
localRenderer: _localRenderer,
remoteRenderer: _remoteRenderer,
- stream: stream,
constraints: constraints,
onButtonBarVisibleStreamController: _onButtonBarVisibleStreamController,
onButtonBarHeightStreamController: _onButtonBarHeightStreamController,
@@ -130,26 +172,25 @@ class _CallHomePageState extends State {
}
Function _onAudioEnable() {
- bool enabled = stream.getAudioTracks()[0].enabled;
- stream.getAudioTracks()[0].enabled = !enabled;
- _audioButton.add(!enabled);
+ final audioTrack = localMediaStream.getAudioTracks()[0];
+ final mute = audioTrack.muted;
+ Helper.setMicrophoneMute(!mute, audioTrack);
+ _audioButton.add(mute);
}
Function _onVideoEnabled() {
- bool enabled = stream.getVideoTracks()[0].enabled;
- stream.getVideoTracks()[0].enabled = !enabled;
- _videoButton.add(!enabled);
+ final videoTrack = localMediaStream.getVideoTracks()[0];
+ bool videoEnabled = videoTrack.enabled;
+ localMediaStream.getVideoTracks()[0].enabled = !videoEnabled;
+ _videoButton.add(!videoEnabled);
}
Function _onSwitchCamera() {
- // stream.getAudioTracks()[0].enabled = false;
- // stream.getVideoTracks()[0].enabled = false;
- Helper.switchCamera(stream.getVideoTracks()[0]);
+ Helper.switchCamera(localMediaStream.getVideoTracks()[0]);
}
void _onShowBar() {
setState(() {
- SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
});
_onButtonBarVisibleStreamController.add(true);
}
@@ -166,7 +207,10 @@ class _CallHomePageState extends State {
}
Future _onHangup() async {
+ signaling.hangupCall(widget.callerId, widget.receiverId);
print('onHangup');
Navigator.of(context).pop();
}
+
+
}
diff --git a/lib/pages/conference/web_rtc/widgets/cam_view_widget.dart b/lib/pages/conference/web_rtc/widgets/cam_view_widget.dart
index 3db0c74b..d27dad55 100644
--- a/lib/pages/conference/web_rtc/widgets/cam_view_widget.dart
+++ b/lib/pages/conference/web_rtc/widgets/cam_view_widget.dart
@@ -9,12 +9,12 @@ import 'draggable_cam.dart';
class CamViewWidget extends StatefulWidget {
RTCVideoRenderer localRenderer;
RTCVideoRenderer remoteRenderer;
- MediaStream stream;
+ MediaStream localStream;
BoxConstraints constraints;
StreamController onButtonBarVisibleStreamController;
StreamController onButtonBarHeightStreamController;
- CamViewWidget({this.localRenderer, this.remoteRenderer, this.stream, this.constraints, this.onButtonBarVisibleStreamController, this.onButtonBarHeightStreamController});
+ CamViewWidget({this.localRenderer, this.remoteRenderer, this.constraints, this.onButtonBarVisibleStreamController, this.onButtonBarHeightStreamController});
@override
_CamViewWidgetState createState() => _CamViewWidgetState();
@@ -24,16 +24,6 @@ class _CamViewWidgetState extends State {
@override
void initState() {
super.initState();
- Future.delayed(const Duration(milliseconds: 300), () {
- showCamera();
- });
- }
-
- showCamera() async {
- setState(() async {
- widget.localRenderer.srcObject = widget.stream;
- widget.remoteRenderer.srcObject = widget.stream;
- });
}
@override
@@ -43,15 +33,18 @@ class _CamViewWidgetState extends State {
height: double.infinity,
child: Stack(
children: [
- Container(
- child: RTCVideoView(widget.localRenderer, mirror: true),
+ FractionallySizedBox(
+ heightFactor: 1, widthFactor: 1,
+ child: Container(
+ child: RTCVideoView(widget.remoteRenderer, mirror: true),
+ ),
),
DraggableCam(
key: Key('publisher'),
onButtonBarHeight: widget.onButtonBarHeightStreamController.stream,
onButtonBarVisible: widget.onButtonBarVisibleStreamController.stream,
availableScreenSize: widget.constraints.biggest,
- child: RTCVideoView(widget.remoteRenderer),
+ child: RTCVideoView(widget.localRenderer),
),
// Expanded(child: RTCVideoView(widget.remoteRenderer)),
],
diff --git a/lib/pages/final_products_page.dart b/lib/pages/final_products_page.dart
index 91e953ad..253d7c08 100644
--- a/lib/pages/final_products_page.dart
+++ b/lib/pages/final_products_page.dart
@@ -93,6 +93,8 @@ class _FinalProductsPageState extends State {
isShowAppBar: true,
backgroundColor: Colors.white,
isShowDecPage: false,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
baseViewModel: model,
body: Container(
height: MediaQuery.of(context).size.height * 5.87,
@@ -485,7 +487,7 @@ class _FinalProductsPageState extends State {
color: CustomColors.green,
),
onPressed: () async {
- if (model.finalProducts[index].rxMessage == null) {
+ if (model.finalProducts[index].isRx == false) {
GifLoaderDialogUtils.showMyDialog(context);
await addToCartFunction(1, model.finalProducts[index].id);
GifLoaderDialogUtils.hideDialog(context);
diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart
index 2bca7a9e..db41840d 100644
--- a/lib/pages/landing/landing_page.dart
+++ b/lib/pages/landing/landing_page.dart
@@ -204,10 +204,15 @@ class _LandingPageState extends State with WidgetsBindingObserver {
AppGlobal.context = context;
if (state == AppLifecycleState.resumed) {
if (LandingPage.isOpenCallPage) {
+ if (Platform.isAndroid) {
+ return;
+ }
if (!isPageNavigated) {
isPageNavigated = true;
Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: LandingPage.incomingCallData))).then((value) {
- isPageNavigated = false;
+ Future.delayed(Duration(seconds: 5), () {
+ isPageNavigated = false;
+ });
});
}
}
@@ -329,12 +334,17 @@ class _LandingPageState extends State with WidgetsBindingObserver {
Map myMap = new Map.from(message['data']);
print(myMap);
+ if (LandingPage.isOpenCallPage) {
+ return;
+ }
LandingPage.isOpenCallPage = true;
LandingPage.incomingCallData = IncomingCallData.fromJson(myMap);
if (!isPageNavigated) {
isPageNavigated = true;
Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: LandingPage.incomingCallData))).then((value) {
- isPageNavigated = false;
+ Future.delayed(Duration(seconds: 5), () {
+ isPageNavigated = false;
+ });
});
}
} else {
diff --git a/lib/pages/livecare/incoming_call.dart b/lib/pages/livecare/incoming_call.dart
index a463fc00..7e586942 100644
--- a/lib/pages/livecare/incoming_call.dart
+++ b/lib/pages/livecare/incoming_call.dart
@@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/models/LiveCare/room_model.dart';
import 'package:diplomaticquarterapp/pages/conference/conference_page.dart';
import 'package:diplomaticquarterapp/pages/conference/web_rtc/call_home_page.dart';
import 'package:diplomaticquarterapp/pages/conference/widgets/platform_exception_alert_dialog.dart';
+import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
@@ -135,6 +136,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt
Container(
child: RawMaterialButton(
onPressed: () {
+ LandingPage.isOpenCallPage = false;
backToHome();
},
elevation: 2.0,
diff --git a/lib/pages/packages_offers/OfferAndPackagesCartPage.dart b/lib/pages/packages_offers/OfferAndPackagesCartPage.dart
index f4743d2c..cd640f6f 100644
--- a/lib/pages/packages_offers/OfferAndPackagesCartPage.dart
+++ b/lib/pages/packages_offers/OfferAndPackagesCartPage.dart
@@ -263,13 +263,18 @@ class _PackagesCartPageState extends State with AfterLayoutMix
}
fetchData() async {
- await viewModel.service.cartItems(context: context).then((value) {
- subtotal = value['subtotal'] ?? 0.0;
- tax = value['tax'] ?? 0.0;
- total = value['total'] ?? 0.0;
- }).catchError((error) {});
-
- setState(() {});
+ final cartResponse = await viewModel.service.cartItems(context: context).catchError((error) {});
+ if(cartResponse != null){
+ subtotal = cartResponse['subtotal'] ?? 0.0;
+ tax = cartResponse['tax'] ?? 0.0;
+ total = cartResponse['total'] ?? 0.0;
+ viewModel.service.getTamaraOptions(context: context, showLoading: true).then((tamara_options){
+ if(tamara_options != null || tamara_options.isNotEmpty) {
+ viewModel.setTamaraIllegablity(total);
+ setState(() {});
+ }
+ });
+ }
}
paymentClosed({@required int orderId, @required bool withStatus, dynamic data}) async {
@@ -282,6 +287,7 @@ class _PackagesCartPageState extends State with AfterLayoutMix
debugPrint(error);
});
}
+
}
// Widget _payNow(BuildContext context, {double subtotal, double tax, double total, @required VoidCallback onPayNowClick}) {
diff --git a/lib/pages/parent_categorise_page.dart b/lib/pages/parent_categorise_page.dart
index 4e58225e..393cbb27 100644
--- a/lib/pages/parent_categorise_page.dart
+++ b/lib/pages/parent_categorise_page.dart
@@ -84,7 +84,8 @@ class _ParentCategorisePageState extends State {
isShowAppBar: true,
backgroundColor: Colors.white,
isShowDecPage: false,
- baseViewModel: model,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,baseViewModel: model,
body: SmartRefresher(
enablePullDown: false,
controller: controller,
@@ -469,7 +470,7 @@ class _ParentCategorisePageState extends State {
GifLoaderDialogUtils.showMyDialog(context);
await model.getFilteredProducts(
- min: minField.text.toString(), max: maxField.text.toString(), categoryId: categoriesId, brandId: brandIds);
+ min: minField.text.isEmpty ? "" : "&price_min=" + minField.text.toString(), max: maxField.text.isEmpty ? "" : "&price_max=" + maxField.text.toString(), categoryId: categoriesId, brandId: brandIds.isEmpty ? "" : "&manufacturerids=" + brandIds);
GifLoaderDialogUtils.hideDialog(context);
Navigator.pop(context);
@@ -896,7 +897,7 @@ class _ParentCategorisePageState extends State {
color: CustomColors.green,
),
onPressed: () async {
- if (model.parentProducts[index].rxMessage == null) {
+ if (model.parentProducts[index].isRx == false) {
GifLoaderDialogUtils.showMyDialog(context);
await addToCartFunction(1, model.parentProducts[index].id);
GifLoaderDialogUtils.hideDialog(context);
diff --git a/lib/pages/pharmacies/ProductCheckTypeWidget.dart b/lib/pages/pharmacies/ProductCheckTypeWidget.dart
index d0a112c6..8ac83fd2 100644
--- a/lib/pages/pharmacies/ProductCheckTypeWidget.dart
+++ b/lib/pages/pharmacies/ProductCheckTypeWidget.dart
@@ -37,6 +37,7 @@ class _ProductCheckTypeWidgetState extends State {
productImage: widget.model.wishListList[index].product.images[0].src,
productID: widget.model.wishListList[index].product.id,
onDelete: deleteWishListItem,
+ isRx:widget.model.wishListList[index].product.isRx,
),
),
diff --git a/lib/pages/pharmacies/compare.dart b/lib/pages/pharmacies/compare.dart
index 82a11610..f458304f 100644
--- a/lib/pages/pharmacies/compare.dart
+++ b/lib/pages/pharmacies/compare.dart
@@ -33,6 +33,9 @@ class _ComparePageState extends State {
appBarTitle: TranslationBase.of(context).compare,
isShowAppBar: true,
isPharmacy: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
+ isBottomBar: true,
body: SingleChildScrollView(
child: Container(
child: compareList(),
diff --git a/lib/pages/pharmacies/my_reviews.dart b/lib/pages/pharmacies/my_reviews.dart
index 08ba3d14..39304cac 100644
--- a/lib/pages/pharmacies/my_reviews.dart
+++ b/lib/pages/pharmacies/my_reviews.dart
@@ -26,6 +26,9 @@ class _MyReviewsPageState extends State {
appBarTitle: TranslationBase.of(context).reviews,
isShowAppBar: true,
isPharmacy: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
+ isBottomBar: true,
baseViewModel: model,
body: model.reviewListList.length == 0
? Container(
diff --git a/lib/pages/pharmacies/screens/product-details/shared/product_details_app_bar.dart b/lib/pages/pharmacies/screens/product-details/shared/product_details_app_bar.dart
index 9ed3c037..18749662 100644
--- a/lib/pages/pharmacies/screens/product-details/shared/product_details_app_bar.dart
+++ b/lib/pages/pharmacies/screens/product-details/shared/product_details_app_bar.dart
@@ -3,6 +3,7 @@ import 'package:diplomaticquarterapp/core/service/AuthenticatedUserObject.dart';
import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/OrderPreviewViewModel.dart';
import 'package:diplomaticquarterapp/core/viewModels/pharmacyModule/product_detail_view_model.dart';
import 'package:diplomaticquarterapp/pages/landing/landing_page_pharmcy.dart';
+import 'package:diplomaticquarterapp/pages/pharmacies/screens/cart-page/cart-order-page.dart';
import 'package:diplomaticquarterapp/pages/pharmacies/screens/product-details/product-detail.dart';
import 'package:diplomaticquarterapp/uitl/app_toast.dart';
import 'package:diplomaticquarterapp/uitl/navigation_service.dart';
@@ -26,9 +27,19 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
final bool isInWishList;
final Function addToCartFunction;
- ProductAppBar({Key key, this.product, this.model, this.addToWishlistFunction, this.quantity, this.deleteFromWishlistFunction, this.isInWishList, this.addToCartFunction}) : super(key: key);
+ ProductAppBar(
+ {Key key,
+ this.product,
+ this.model,
+ this.addToWishlistFunction,
+ this.quantity,
+ this.deleteFromWishlistFunction,
+ this.isInWishList,
+ this.addToCartFunction})
+ : super(key: key);
- AuthenticatedUserObject authenticatedUserObject = locator();
+ AuthenticatedUserObject authenticatedUserObject =
+ locator();
@override
Widget build(BuildContext context) {
@@ -66,13 +77,23 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
color: Colors.grey[800],
onPress: () {
Navigator.pushAndRemoveUntil(
- locator().navigatorKey.currentContext, MaterialPageRoute(builder: (context) => LandingPagePharmacy(currentTab: 3)), (Route r) => false);
+ locator()
+ .navigatorKey
+ .currentContext,
+ MaterialPageRoute(
+ builder: (context) =>
+ LandingPagePharmacy(currentTab: 3)),
+ (Route r) => false);
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => CartOrderPage()),
// );
}),
- if (Provider.of(context, listen: false).cartResponse.quantityCount != 0)
+ if (Provider.of(context,
+ listen: false)
+ .cartResponse
+ .quantityCount !=
+ 0)
Positioned(
top: 0,
right: -1.0,
@@ -85,7 +106,11 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
height: 18,
child: Center(
child: Texts(
- Provider.of(context, listen: false).cartResponse.quantityCount.toString(),
+ Provider.of(context,
+ listen: false)
+ .cartResponse
+ .quantityCount
+ .toString(),
style: "caption",
medium: true,
color: Colors.white,
@@ -124,7 +149,7 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
return Container(
child: new Wrap(
children: [
- if (product.stockAvailability != 'Out of stock' && !product.isRx)
+ if (product.stockAvailability != 'Out of stock' && product.isRx != true)
new ListTile(
leading: Icon(Icons.shopping_cart),
title: Text(
@@ -133,12 +158,18 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
onTap: () async {
if (quantity > 0) {
{
- await addToCartFunction(quantity: quantity, itemID: itemID, model: model);
+ await addToCartFunction(
+ quantity: quantity,
+ itemID: itemID,
+ model: model);
Navigator.of(context).pop();
}
} else {
- AppToast.showErrorToast(message: TranslationBase.of(context).addQuantity);
+ AppToast.showErrorToast(
+ message: TranslationBase.of(context).addQuantity
+ // "you should add quantity"
+ );
}
}),
ListTile(
@@ -147,7 +178,9 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
color: !isInWishList ? Colors.white : Colors.red[800],
),
title: Text(
- isInWishList ? TranslationBase.of(context).removeFromWishlist : TranslationBase.of(context).addToWishlist,
+ isInWishList
+ ? TranslationBase.of(context).removeFromWishlist
+ : TranslationBase.of(context).addToWishlist,
),
onTap: () async {
if (isInWishList)
@@ -162,7 +195,8 @@ class ProductAppBar extends StatelessWidget with PreferredSizeWidget {
TranslationBase.of(context).compare,
),
onTap: () {
- Provider.of(context, listen: false).addItem(specificationData, context);
+ Provider.of(context, listen: false)
+ .addItem(specificationData, context);
Navigator.of(context).pop();
},
),
diff --git a/lib/pages/pharmacies/widgets/ProductOrderItem.dart b/lib/pages/pharmacies/widgets/ProductOrderItem.dart
index afe74371..8d74cb48 100644
--- a/lib/pages/pharmacies/widgets/ProductOrderItem.dart
+++ b/lib/pages/pharmacies/widgets/ProductOrderItem.dart
@@ -252,7 +252,7 @@ class _ProductOrderItemState extends State {
}
_quantityController.text = "${widget.item.quantity}";
_totalPrice =
- "${(widget.item.product.price * widget.item.quantity).toStringAsFixed(2)}";
+ "${(widget.item.product.price * widget.item.quantity).toStringAsFixed(2)}";
}
});
}
diff --git a/lib/pages/pharmacies/wishlist.dart b/lib/pages/pharmacies/wishlist.dart
index 3d1c8114..00088b59 100644
--- a/lib/pages/pharmacies/wishlist.dart
+++ b/lib/pages/pharmacies/wishlist.dart
@@ -17,6 +17,9 @@ class WishlistPage extends StatelessWidget {
isShowAppBar: true,
isShowDecPage: false,
isPharmacy: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
+ isBottomBar: true,
baseViewModel: model,
body: model.wishListList.length == 0
? Container(
@@ -35,8 +38,8 @@ class WishlistPage extends StatelessWidget {
),
Padding(
padding: const EdgeInsets.all(8.0),
- child: Text(
- 'There is no data',
+ child: Text(TranslationBase.of(context).noData,
+ // 'There is no data',
style: TextStyle(fontSize: 30),
),
)
diff --git a/lib/pages/pharmacy/order/Order.dart b/lib/pages/pharmacy/order/Order.dart
index 9eda1004..ef5c9346 100644
--- a/lib/pages/pharmacy/order/Order.dart
+++ b/lib/pages/pharmacy/order/Order.dart
@@ -66,6 +66,9 @@ class _OrderPageState extends State with SingleTickerProviderStateMix
baseViewModel: model,
isShowAppBar: true,
isPharmacy: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
+ isBottomBar: true,
body: Container(
child: Column(
children: [
diff --git a/lib/pages/pharmacy/order/OrderDetails.dart b/lib/pages/pharmacy/order/OrderDetails.dart
index fc4ae184..6b7c957e 100644
--- a/lib/pages/pharmacy/order/OrderDetails.dart
+++ b/lib/pages/pharmacy/order/OrderDetails.dart
@@ -84,6 +84,9 @@ class _OrderDetailsPageState extends State {
appBarTitle: TranslationBase.of(context).orderDetail,
isShowAppBar: true,
isPharmacy: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
+ isBottomBar: true,
baseViewModel: model,
body: model.orderListModel.length > 0
? Container(
diff --git a/lib/pages/pharmacy/profile/profile.dart b/lib/pages/pharmacy/profile/profile.dart
index 1f2520b6..72fa43dc 100644
--- a/lib/pages/pharmacy/profile/profile.dart
+++ b/lib/pages/pharmacy/profile/profile.dart
@@ -108,10 +108,10 @@ class _ProfilePageState extends State {
builder: (_, model, wi) => AppScaffold(
appBarTitle: TranslationBase.of(context).myAccount,
isShowAppBar: true,
- isShowDecPage: true,
+ isShowDecPage: false,
isPharmacy: true,
-
- //isBottomBar: true,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
isMainPharmacyPages: true,
body: user != null
? Container(
diff --git a/lib/pages/sub_categories_modalsheet.dart b/lib/pages/sub_categories_modalsheet.dart
index d6499c8e..ed2403db 100644
--- a/lib/pages/sub_categories_modalsheet.dart
+++ b/lib/pages/sub_categories_modalsheet.dart
@@ -40,11 +40,13 @@ class _SubCategoriseModalsheetState extends State {
builder: (_, model, wi) => AppScaffold(
// appBarTitle: titleName,
appBarTitle: TranslationBase.of(context).categorise,
- isBottomBar: false,
+ isBottomBar: true,
isShowAppBar: true,
isPharmacy: true,
backgroundColor: Colors.white,
isShowDecPage: false,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
baseViewModel: model,
body: Container(
color: Colors.white,
@@ -77,7 +79,11 @@ class _SubCategoriseModalsheetState extends State {
context,
FadePage(
page: SubCategorisePage(
- title: model.categoriseParent[index].name,
+ title: projectViewModel
+ .isArabic
+ ? model.categoriseParent[index].namen
+ : model.categoriseParent[index].name,
+ // title: model.categoriseParent[index].name,
id: model.categoriseParent[index].id,
parentId: id,
)),
diff --git a/lib/pages/sub_categorise_page.dart b/lib/pages/sub_categorise_page.dart
index 4bc069dc..1856aedb 100644
--- a/lib/pages/sub_categorise_page.dart
+++ b/lib/pages/sub_categorise_page.dart
@@ -14,6 +14,7 @@ import 'package:diplomaticquarterapp/uitl/utils.dart';
import 'package:diplomaticquarterapp/widgets/buttons/button.dart';
import 'package:diplomaticquarterapp/widgets/data_display/text.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_pharmacy_widget.dart';
+import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/others/entity_checkbox_list.dart';
import 'package:diplomaticquarterapp/widgets/others/network_base_view.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
@@ -76,12 +77,15 @@ class _SubCategorisePageState extends State {
allowAny: true,
builder: (BuildContext context, PharmacyCategoriseViewModel model,
Widget child) =>
- PharmacyAppScaffold(
+ AppScaffold(
+ isPharmacy: true,
appBarTitle: title,
- isBottomBar: false,
+ isBottomBar: true,
isShowAppBar: true,
backgroundColor: Colors.white,
isShowDecPage: false,
+ showPharmacyCart: false,
+ showHomeAppBarIcon: false,
baseViewModel: model,
body: SmartRefresher(
controller: controller,
@@ -643,16 +647,20 @@ class _SubCategorisePageState extends State {
context);
await model.getFilteredSubProducts(
- min: minField
- .text
- .toString(),
- max: maxField
- .text
- .toString(),
+ min: minField.text.isEmpty
+ ? ""
+ : minField.text
+ .toString(),
+ max: maxField.text.isEmpty
+ ? ""
+ : maxField.text
+ .toString(),
categoryId:
categoriesId,
- brandId:
- brandIds);
+ brandId: brandIds.isEmpty
+ ? ""
+ : "&manufacturerids=" +
+ brandIds);
GifLoaderDialogUtils
.hideDialog(
context);
@@ -1215,8 +1223,7 @@ class _SubCategorisePageState extends State {
if (model
.subProducts[
index]
- .rxMessage ==
- null) {
+ .isRx == false) {
GifLoaderDialogUtils
.showMyDialog(
context);
diff --git a/lib/pages/webRTC/call_page.dart b/lib/pages/webRTC/call_page.dart
index c5b41aa3..0c6caf54 100644
--- a/lib/pages/webRTC/call_page.dart
+++ b/lib/pages/webRTC/call_page.dart
@@ -1,8 +1,20 @@
+import 'dart:io';
+
+import 'package:diplomaticquarterapp/models/LiveCare/IncomingCallData.dart';
+import 'package:diplomaticquarterapp/pages/landing/landing_page.dart';
+import 'package:diplomaticquarterapp/pages/livecare/incoming_call.dart';
import 'package:diplomaticquarterapp/pages/webRTC/signaling.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
+import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
+final DOCTOR_TOKEN = 'cj2TFgotT6q-F0SCGVFaKR:APA91bFBY0NCY5tlCooYMKS9JWI8TMJQ6YcPLT0T5gNyn-qjfQgFVQWh60QeXDz_aNqL2U3B9qOjpDbaA32e4oBlK1klR-7uUYL0DwWiHKnU1hV_wlW9-Tib16CBVkN3ods7OMlKbPv9';
+String My_ID = '54321';
+String My_Mobile = '0500409598';
+String doctor_ID = '12345';
+String doctor_Mobile = '966500409598';
+
class CallPage extends StatefulWidget {
@override
_CallPageState createState() => _CallPageState();
@@ -20,10 +32,12 @@ class _CallPageState extends State {
_localRenderer.initialize();
_remoteRenderer.initialize();
- signaling.onAddRemoteStream = ((stream) {
- _remoteRenderer.srcObject = stream;
- setState(() {});
- });
+ // signaling.onRemoteStream = ((stream) {
+ // _remoteRenderer.srcObject = stream;
+ // setState(() {});
+ // });
+
+ fcmConfigure();
super.initState();
}
@@ -35,24 +49,13 @@ class _CallPageState extends State {
super.dispose();
}
- void _getUserMedia() async {
- final Map constraints = {
- 'audio': 'false',
- 'video': {'facingMode': 'user'},
- };
-
- MediaStream stream = await navigator.mediaDevices.getUserMedia(constraints);
- setState(() {
- _localRenderer.srcObject = stream;
- });
- }
-
- void initializeRenderers() async {
- _localRenderer.initialize();
- }
@override
Widget build(BuildContext context) {
+ FirebaseMessaging().getToken().then((value){
+ print('FCM_TOKEN: $value');
+ });
+
return AppScaffold(
isShowAppBar: true,
showNewAppBar: true,
@@ -64,44 +67,21 @@ class _CallPageState extends State {
SizedBox(height: 8),
Wrap(
children: [
- ElevatedButton(
- onPressed: () {
- setState(() {
- signaling.openUserMedia(_localRenderer, _remoteRenderer);
- });
- },
- child: Text("Open camera & microphone"),
- ),
- SizedBox(
- width: 8,
- ),
- ElevatedButton(
- onPressed: () async {
- // roomId = await signaling.createRoom(_remoteRenderer);
- textEditingController.text = roomId;
- setState(() {});
- },
- child: Text("Create room"),
- ),
SizedBox(
width: 8,
),
ElevatedButton(
onPressed: () {
- // Add roomId
- // signaling.joinRoom(
- // textEditingController.text,
- // _remoteRenderer,
- // );
+ dummyCall();
},
- child: Text("Join room"),
+ child: Text("Call"),
),
SizedBox(
width: 8,
),
ElevatedButton(
onPressed: () {
- // signaling.hangUp(_localRenderer);
+ signaling.hangUp(_localRenderer);
},
child: Text("Hangup"),
)
@@ -143,5 +123,57 @@ class _CallPageState extends State {
],
),
);
+
}
+
+ dummyCall() async{
+ final json = {
+ "callerID": "12345",
+ "receiverID": "54321",
+ "msgID": "123",
+ "notfID": "123",
+ "notification_foreground": "true",
+ "count": "1",
+ "message": "Doctor is calling ",
+ "AppointmentNo": "123",
+ "title": "Rayyan Hospital",
+ "ProjectID": "123",
+ "NotificationType": "10",
+ "background": "1",
+ "doctorname": "Dr Sulaiman Al Habib",
+ "clinicname": "ENT Clinic",
+ "speciality": "Speciality",
+ "appointmentdate": "Sun, 15th Dec, 2019",
+ "appointmenttime": "09:00",
+ "type": "video",
+ "session_id": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
+ "identity": "Haroon1",
+ "name": "SmallDailyStandup",
+ "videoUrl": "video",
+ "picture": "video",
+ "is_call": "true"
+ };
+
+ IncomingCallData incomingCallData = IncomingCallData.fromJson(json);
+ final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
+ }
+
+ fcmConfigure(){
+ FirebaseMessaging().configure(
+ onMessage: (message) async{
+ print(message.toString());
+
+ IncomingCallData incomingCallData;
+ if(Platform.isAndroid)
+ incomingCallData = IncomingCallData.fromJson(message['data']);
+ else if(Platform.isIOS)
+ incomingCallData = IncomingCallData.fromJson(message);
+ if(incomingCallData != null)
+ final result = await Navigator.push(context, MaterialPageRoute(builder: (context) => IncomingCall(incomingCallData: incomingCallData)));
+
+ }
+ );
+ }
+
+
}
diff --git a/lib/pages/webRTC/call_page_bkp.dart b/lib/pages/webRTC/call_page_bkp.dart
new file mode 100644
index 00000000..4a31feae
--- /dev/null
+++ b/lib/pages/webRTC/call_page_bkp.dart
@@ -0,0 +1,147 @@
+// import 'package:diplomaticquarterapp/pages/webRTC/signaling_bkp.dart';
+// import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
+// import 'package:flutter/material.dart';
+// import 'package:flutter_webrtc/flutter_webrtc.dart';
+//
+// class CallPage extends StatefulWidget {
+// @override
+// _CallPageState createState() => _CallPageState();
+// }
+//
+// class _CallPageState extends State {
+// Signaling signaling = Signaling();
+// RTCVideoRenderer _localRenderer = RTCVideoRenderer();
+// RTCVideoRenderer _remoteRenderer = RTCVideoRenderer();
+// String roomId;
+// TextEditingController textEditingController = TextEditingController(text: '');
+//
+// @override
+// void initState() {
+// _localRenderer.initialize();
+// _remoteRenderer.initialize();
+//
+// signaling.onAddRemoteStream = ((stream) {
+// _remoteRenderer.srcObject = stream;
+// setState(() {});
+// });
+//
+// super.initState();
+// }
+//
+// @override
+// void dispose() {
+// _localRenderer.dispose();
+// _remoteRenderer.dispose();
+// super.dispose();
+// }
+//
+// void _getUserMedia() async {
+// final Map constraints = {
+// 'audio': 'false',
+// 'video': {'facingMode': 'user'},
+// };
+//
+// MediaStream stream = await navigator.mediaDevices.getUserMedia(constraints);
+// setState(() {
+// _localRenderer.srcObject = stream;
+// });
+// }
+//
+// void initializeRenderers() async {
+// _localRenderer.initialize();
+// }
+//
+// @override
+// Widget build(BuildContext context) {
+// return AppScaffold(
+// isShowAppBar: true,
+// showNewAppBar: true,
+// showNewAppBarTitle: true,
+// isShowDecPage: false,
+// appBarTitle: "WebRTC Calling",
+// body: Column(
+// children: [
+// SizedBox(height: 8),
+// Wrap(
+// children: [
+// ElevatedButton(
+// onPressed: () {
+// setState(() {
+// signaling.openUserMedia(_localRenderer, _remoteRenderer);
+// });
+// },
+// child: Text("Open camera & microphone"),
+// ),
+// SizedBox(
+// width: 8,
+// ),
+// ElevatedButton(
+// onPressed: () async {
+// roomId = await signaling.createRoom(_remoteRenderer);
+// textEditingController.text = roomId;
+// setState(() {});
+// },
+// child: Text("Create room"),
+// ),
+// SizedBox(
+// width: 8,
+// ),
+// ElevatedButton(
+// onPressed: () {
+// // Add roomId
+// signaling.joinRoom(
+// textEditingController.text,
+// _remoteRenderer,
+// );
+// },
+// child: Text("Join room"),
+// ),
+// SizedBox(
+// width: 8,
+// ),
+// ElevatedButton(
+// onPressed: () {
+// signaling.hangUp(_localRenderer);
+// },
+// child: Text("Hangup"),
+// )
+// ],
+// ),
+// SizedBox(height: 8),
+// Expanded(
+// child: Padding(
+// padding: const EdgeInsets.all(0.0),
+// child: Stack(
+// children: [
+// Positioned(top: 0.0, right: 0.0, left: 0.0, bottom: 0.0, child: RTCVideoView(_remoteRenderer)),
+// Positioned(
+// top: 20.0,
+// right: 100.0,
+// left: 20.0,
+// bottom: 300.0,
+// child: RTCVideoView(_localRenderer, mirror: true),
+// ),
+// ],
+// ),
+// ),
+// ),
+// Padding(
+// padding: const EdgeInsets.all(8.0),
+// child: Row(
+// mainAxisAlignment: MainAxisAlignment.center,
+// children: [
+// Text("Join the following Room: "),
+// Flexible(
+// child: TextFormField(
+// controller: textEditingController,
+// ),
+// )
+// ],
+// ),
+// ),
+// SizedBox(height: 8)
+// ],
+// ),
+// );
+// }
+// }
diff --git a/lib/pages/webRTC/fcm/FCMSendNotification.dart b/lib/pages/webRTC/fcm/FCMSendNotification.dart
new file mode 100644
index 00000000..f67537cf
--- /dev/null
+++ b/lib/pages/webRTC/fcm/FCMSendNotification.dart
@@ -0,0 +1,86 @@
+
+import 'dart:convert';
+
+import 'package:diplomaticquarterapp/core/service/client/base_app_client.dart';
+import 'package:http/http.dart' as http;
+
+const _serverFCMToken = 'ya29.a0ARrdaM9U7fZtxF64ntg2Y1Nve-cd4rPazyGcWN69cQmOsddUqxAL1X8GUQ8V6sW2gWxM8ln1BIbmh0OrzQtCiTGrsmcL3jZlGXoQhZN51nX3O7F3g1AXCW_Zt_pjiworCJEGSRkl7QirxE7RFzlwBONsOuft';
+const doctorID = '12345';
+
+class FCM{
+ static Future sendCallNotifcationTo(String token, String patientID, String patientMobile) async{
+ var headers = {
+ 'Authorization': 'Bearer $_serverFCMToken',
+ 'Content-Type': 'application/json'
+ };
+
+ final body = {
+ "message": {
+ "token": token,
+ "notification": {
+ "title": "Dr Sulaiman Al Habib",
+ "body": "Doctor is calling"
+ },
+ "apns": {
+ "payload": {
+ "aps": {
+ "sound": "ring_30Sec.mp3",
+ "token": "466e0f16fecf1e32c51f812cccc84fcbc807f958b15eb55675a5fa971a775829",
+ "badge": 1
+ }
+ },
+ "headers": {
+ "apns-priority": "10",
+ "apns-expiration": "0",
+ "apns-collapse-id": "2561368006"
+ }
+ },
+ "data": {
+ "callerID" : doctorID,
+ "receiverID" : patientID,
+ "receiverMobile" : patientMobile,
+ "msgID": "123",
+ "notfID": "123",
+ "notification_foreground": "true",
+ "count": "1",
+ "message": "Doctor is calling ",
+ "AppointmentNo": "123",
+ "title": "Rayyan Hospital",
+ "ProjectID": "123",
+ "NotificationType": "10",
+ "background": "1",
+ "doctorname": "Dr Sulaiman Al Habib",
+ "clinicname": "ENT Clinic",
+ "speciality": "Speciality",
+ "appointmentdate": "Sun, 15th Dec, 2019",
+ "appointmenttime": "09:00",
+ "type": "video",
+ "session_id": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIn0.eyJqdGkiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0LTE1OTg3NzQ1MDYiLCJpc3MiOiJTS2I2NjYyOWMzN2ZhOTM3YjFjNDI2Zjg1MTgyNWFmN2M0Iiwic3ViIjoiQUNhYWQ1YTNmOGM2NGZhNjczNTY3NTYxNTc0N2YyNmMyYiIsImV4cCI6MTU5ODc3ODEwNiwiZ3JhbnRzIjp7ImlkZW50aXR5IjoiSGFyb29uMSIsInZpZGVvIjp7InJvb20iOiJTbWFsbERhaWx5U3RhbmR1cCJ9fX0.7XUS5uMQQJfkrBZu9EjQ6STL6R7iXkso6BtO1HmrQKk",
+ "identity": "Haroon1",
+ "name": "SmallDailyStandup",
+ "videoUrl": "video",
+ "picture": "video",
+ "is_call": "true"
+ }
+ }
+ };
+
+ bool success = false;
+ await BaseAppClient().simplePost('https://fcm.googleapis.com/v1/projects/api-project-815750722565/messages:send', body: body, headers: headers, onSuccess: (data, statusCode){
+ success = true;
+ }, onFailure: (error, statusCode){
+ success = false;
+ });
+
+ return success;
+ // final response = await http.post('https://fcm.googleapis.com/v1/projects/api-project-815750722565/messages:send', headers:headers, body: body);
+
+
+ }
+}
+
+String toB64(String data){
+ var bytes = utf8.encode(data);
+ var base64Str = base64.encode(bytes);
+ return base64Str;
+}
\ No newline at end of file
diff --git a/lib/pages/webRTC/signaling.dart b/lib/pages/webRTC/signaling.dart
index 3f840854..90127e31 100644
--- a/lib/pages/webRTC/signaling.dart
+++ b/lib/pages/webRTC/signaling.dart
@@ -1,11 +1,45 @@
import 'dart:convert';
-// import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:diplomaticquarterapp/pages/webRTC/fcm/FCMSendNotification.dart';
+import 'package:diplomaticquarterapp/uitl/SignalRUtil.dart';
+import 'package:flutter/cupertino.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
+import 'call_page.dart';
+
typedef void StreamStateCallback(MediaStream stream);
+typedef void RTCIceGatheringStateCallback(RTCIceGatheringState state);
+typedef void RTCPeerConnectionStateCallback(RTCPeerConnectionState state);
+typedef void RTCSignalingStateCallback(RTCSignalingState state);
class Signaling {
+
+ dispose(){
+ if(peerConnection != null)
+ peerConnection.dispose();
+ signalR.closeConnection();
+ }
+
+ init(){
+ // Create Peer Connection
+ createPeerConnection(configuration).then((value){
+ peerConnection = value;
+ registerPeerConnectionListeners();
+ });
+ }
+
+
+ initializeSignalR() async{
+ if(signalR != null)
+ await signalR.closeConnection();
+
+ signalR = SignalRUtil(hubName: "https://VCallApi.hmg.com/WebRTCHub?source=$My_Mobile&username=$My_ID");
+ final connected = await signalR.openConnection();
+ if(!connected)
+ throw 'Failed to connect SignalR';
+ }
+
Map configuration = {
'iceServers': [
{
@@ -14,209 +48,96 @@ class Signaling {
]
};
+ SignalRUtil signalR;
+
RTCPeerConnection peerConnection;
MediaStream localStream;
MediaStream remoteStream;
- String roomId;
- String currentRoomText;
- StreamStateCallback onAddRemoteStream;
-
- // Future createRoom(RTCVideoRenderer remoteRenderer) async {
- // // FirebaseFirestore db = FirebaseFirestore.instance;
- // // DocumentReference roomRef = db.collection('rooms').doc();
- //
- // print('Create PeerConnection with configuration: $configuration');
- //
- // peerConnection = await createPeerConnection(configuration);
- //
- // registerPeerConnectionListeners();
- //
- // localStream.getTracks().forEach((track) {
- // peerConnection?.addTrack(track, localStream);
- // });
- //
- // // Code for collecting ICE candidates below
- // var callerCandidatesCollection = roomRef.collection('callerCandidates');
- //
- // peerConnection?.onIceCandidate = (RTCIceCandidate candidate) {
- // print('Got candidate: ${candidate.toMap()}');
- // callerCandidatesCollection.add(candidate.toMap());
- // };
- // // Finish Code for collecting ICE candidate
- //
- // // Add code for creating a room
- // RTCSessionDescription offer = await peerConnection.createOffer();
- // await peerConnection.setLocalDescription(offer);
- // print('Created offer: $offer');
- //
- // Map roomWithOffer = {'offer': offer.toMap()};
- //
- // await roomRef.set(roomWithOffer);
- // var roomId = roomRef.id;
- // print('New room created with SDK offer. Room ID: $roomId');
- // currentRoomText = 'Current room is $roomId - You are the caller!';
- // // Created a Room
- //
- // peerConnection?.onTrack = (RTCTrackEvent event) {
- // print('Got remote track: ${event.streams[0]}');
- //
- // event.streams[0].getTracks().forEach((track) {
- // print('Add a track to the remoteStream $track');
- // remoteStream?.addTrack(track);
- // });
- // };
- //
- // // Listening for remote session description below
- // roomRef.snapshots().listen((snapshot) async {
- // print('Got updated room: ${snapshot.data()}');
- //
- // Map data = snapshot.data() as Map;
- // if (peerConnection?.getRemoteDescription() != null && data['answer'] != null) {
- // var answer = RTCSessionDescription(
- // data['answer']['sdp'],
- // data['answer']['type'],
- // );
- //
- // print("Someone tried to connect");
- // await peerConnection?.setRemoteDescription(answer);
- // }
- // });
- // // Listening for remote session description above
- //
- // // Listen for remote Ice candidates below
- // roomRef.collection('calleeCandidates').snapshots().listen((snapshot) {
- // snapshot.docChanges.forEach((change) {
- // if (change.type == DocumentChangeType.added) {
- // Map data = change.doc.data() as Map;
- // print('Got new remote ICE candidate: ${jsonEncode(data)}');
- // peerConnection.addCandidate(
- // RTCIceCandidate(
- // data['candidate'],
- // data['sdpMid'],
- // data['sdpMLineIndex'],
- // ),
- // );
- // }
- // });
- // });
- // // Listen for remote ICE candidates above
- //
- // return roomId;
- // }
-
- // Future joinRoom(String roomId, RTCVideoRenderer remoteVideo) async {
- // FirebaseFirestore db = FirebaseFirestore.instance;
- // DocumentReference roomRef = db.collection('rooms').doc('$roomId');
- // var roomSnapshot = await roomRef.get();
- // print('Got room ${roomSnapshot.exists}');
- //
- // if (roomSnapshot.exists) {
- // print('Create PeerConnection with configuration: $configuration');
- // peerConnection = await createPeerConnection(configuration);
- //
- // registerPeerConnectionListeners();
- //
- // localStream.getTracks().forEach((track) {
- // peerConnection?.addTrack(track, localStream);
- // });
- //
- // // Code for collecting ICE candidates below
- // var calleeCandidatesCollection = roomRef.collection('calleeCandidates');
- // peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
- // if (candidate == null) {
- // print('onIceCandidate: complete!');
- // return;
- // }
- // print('onIceCandidate: ${candidate.toMap()}');
- // calleeCandidatesCollection.add(candidate.toMap());
- // };
- // // Code for collecting ICE candidate above
- //
- // peerConnection?.onTrack = (RTCTrackEvent event) {
- // print('Got remote track: ${event.streams[0]}');
- // event.streams[0].getTracks().forEach((track) {
- // print('Add a track to the remoteStream: $track');
- // remoteStream?.addTrack(track);
- // });
- // };
- //
- // // Code for creating SDP answer below
- // var data = roomSnapshot.data() as Map;
- // print('Got offer $data');
- // var offer = data['offer'];
- // await peerConnection?.setRemoteDescription(
- // RTCSessionDescription(offer['sdp'], offer['type']),
- // );
- // var answer = await peerConnection.createAnswer();
- // print('Created Answer $answer');
- //
- // await peerConnection.setLocalDescription(answer);
- //
- // Map roomWithAnswer = {
- // 'answer': {'type': answer.type, 'sdp': answer.sdp}
- // };
- //
- // await roomRef.update(roomWithAnswer);
- // // Finished creating SDP answer
- //
- // // Listening for remote ICE candidates below
- // // roomRef.collection('callerCandidates').snapshots().listen((snapshot) {
- // // snapshot.docChanges.forEach((document) {
- // // var data = document.doc.data() as Map;
- // // print(data);
- // // print('Got new remote ICE candidate: $data');
- // // peerConnection.addCandidate(
- // // RTCIceCandidate(
- // // data['candidate'],
- // // data['sdpMid'],
- // // data['sdpMLineIndex'],
- // // ),
- // // );
- // // });
- // // });
- // }
- // }
-
- Future openUserMedia(
- RTCVideoRenderer localVideo,
- RTCVideoRenderer remoteVideo,
- ) async {
- var stream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': false});
-
- localVideo.srcObject = stream;
- localStream = stream;
-
- remoteVideo.srcObject = await createLocalMediaStream('key');
+ RTCDataChannel dataChannel;
+
+ Future call(String patientId, String mobile, {@required RTCVideoRenderer localVideo, @required RTCVideoRenderer remoteVideo}) async {
+ initializeSignalR();
+
+ final isCallPlaced = await FCM.sendCallNotifcationTo(DOCTOR_TOKEN, patientId, mobile);
+ if(!isCallPlaced)
+ throw 'Failed to notify target for call';
+
+ return isCallPlaced;
+ }
+
+
+ Future acceptCall(String caller, String receiver, {@required MediaStream localMediaStream, @required Function(MediaStream) onRemoteMediaStream}) async{
+ await initializeSignalR();
+ signalR.setContributors(caller: caller, receiver: receiver);
+ await signalR.acceptCall(receiver, caller).catchError((e) => throw 'Failed to inform signalR that i accepted a call');
+
+ peerConnection.addStream(localMediaStream);
+
+ peerConnection?.onAddStream = (MediaStream stream) {
+ remoteStream = stream;
+ onRemoteMediaStream?.call(stream);
+ };
+
+ return true;
+ }
+
+ Future hangupCall(String caller, String receiver) async{
+ await signalR.hangupCall(caller, receiver);
+ dispose();
}
- // Future hangUp(RTCVideoRenderer localVideo) async {
- // List tracks = localVideo.srcObject.getTracks();
- // tracks.forEach((track) {
- // track.stop();
- // });
- //
- // if (remoteStream != null) {
- // remoteStream.getTracks().forEach((track) => track.stop());
- // }
- // if (peerConnection != null) peerConnection.close();
- //
- // if (roomId != null) {
- // var db = FirebaseFirestore.instance;
- // var roomRef = db.collection('rooms').doc(roomId);
- // var calleeCandidates = await roomRef.collection('calleeCandidates').get();
- // calleeCandidates.docs.forEach((document) => document.reference.delete());
- //
- // var callerCandidates = await roomRef.collection('callerCandidates').get();
- // callerCandidates.docs.forEach((document) => document.reference.delete());
- //
- // await roomRef.delete();
- // }
- //
- // localStream.dispose();
- // remoteStream?.dispose();
- // }
+ answerOffer(String sdp) async{
+ final offer = jsonDecode(sdp);
+ final caller = offer['caller'];
+ final receiver = offer['target'];
+ final offerSdp = offer['sdp'];
+ peerConnection.setRemoteDescription(rtcSessionDescriptionFrom(offerSdp))
+ .then((value) {
+ return peerConnection.createAnswer();
+ })
+ .then((anwser) {
+ return peerConnection.setLocalDescription(anwser);
+ })
+ .then((value) {
+ return peerConnection.getLocalDescription();
+ })
+ .then((answer) {
+ return signalR.answerOffer(answer, caller, receiver);
+ });
+
+ }
+
+ Future hangUp(RTCVideoRenderer localVideo) async {
+
+ }
+
+ Future createSdpAnswer(String toOfferSdp) async {
+ final offerSdp = rtcSessionDescriptionFrom(jsonDecode(toOfferSdp));
+ peerConnection.setRemoteDescription(offerSdp);
+
+ final answer = await peerConnection.createAnswer();
+ var answerSdp = json.encode(answer); // Send SDP via Push or any channel
+ return answerSdp;
+ }
+
+ Future createSdpOffer() async {
+ final offer = await peerConnection.createOffer();
+ await peerConnection.setLocalDescription(offer);
+ final map = offer.toMap();
+ var offerSdp = json.encode(map); // Send SDP via Push or any channel
+ return offerSdp;
+ }
+
+ addCandidate(String candidateJson){
+ peerConnection.addCandidate(rtcIceCandidateFrom(candidateJson));
+ }
void registerPeerConnectionListeners() {
+ peerConnection.onIceCandidate = (RTCIceCandidate candidate){
+ print(json.encode(candidate.toMap()));
+ signalR.addIceCandidate(json.encode(candidate.toMap()));
+ };
+
peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
print('ICE gathering state changed: $state');
};
@@ -228,15 +149,17 @@ class Signaling {
peerConnection?.onSignalingState = (RTCSignalingState state) {
print('Signaling state change: $state');
};
+ }
+}
- peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
- print('ICE connection state change: $state');
- };
- peerConnection?.onAddStream = (MediaStream stream) {
- print("Add remote stream");
- onAddRemoteStream?.call(stream);
- remoteStream = stream;
- };
- }
+rtcSessionDescriptionFrom(Map sdp){
+ return RTCSessionDescription(
+ sdp['sdp'],sdp['type'],
+ );
+}
+
+rtcIceCandidateFrom(String json){
+ final map = jsonDecode(json)['candidate'];
+ return RTCIceCandidate(map['candidate'], map['sdpMid'], map['sdpMLineIndex']);
}
diff --git a/lib/pages/webRTC/signaling_bkp.dart b/lib/pages/webRTC/signaling_bkp.dart
new file mode 100644
index 00000000..f987e285
--- /dev/null
+++ b/lib/pages/webRTC/signaling_bkp.dart
@@ -0,0 +1,242 @@
+import 'dart:convert';
+
+import 'package:cloud_firestore/cloud_firestore.dart';
+import 'package:flutter_webrtc/flutter_webrtc.dart';
+
+typedef void StreamStateCallback(MediaStream stream);
+
+class Signaling {
+ Map configuration = {
+ 'iceServers': [
+ {
+ 'urls': ['stun:stun1.l.google.com:19302', 'stun:stun2.l.google.com:19302']
+ }
+ ]
+ };
+
+ RTCPeerConnection peerConnection;
+ MediaStream localStream;
+ MediaStream remoteStream;
+ String roomId;
+ String currentRoomText;
+ StreamStateCallback onAddRemoteStream;
+
+ Future createRoom(RTCVideoRenderer remoteRenderer) async {
+ FirebaseFirestore db = FirebaseFirestore.instance;
+ DocumentReference roomRef = db.collection('rooms').doc();
+
+ print('Create PeerConnection with configuration: $configuration');
+
+ peerConnection = await createPeerConnection(configuration);
+
+ registerPeerConnectionListeners();
+
+ localStream.getTracks().forEach((track) {
+ peerConnection?.addTrack(track, localStream);
+ });
+
+ // Code for collecting ICE candidates below
+ var callerCandidatesCollection = roomRef.collection('callerCandidates');
+
+ peerConnection?.onIceCandidate = (RTCIceCandidate candidate) {
+ print('Got candidate: ${candidate.toMap()}');
+ callerCandidatesCollection.add(candidate.toMap());
+ };
+ // Finish Code for collecting ICE candidate
+
+ // Add code for creating a room
+ RTCSessionDescription offer = await peerConnection.createOffer();
+ await peerConnection.setLocalDescription(offer);
+ print('Created offer: $offer');
+
+ Map roomWithOffer = {'offer': offer.toMap()};
+
+ await roomRef.set(roomWithOffer);
+ var roomId = roomRef.id;
+ print('New room created with SDK offer. Room ID: $roomId');
+ currentRoomText = 'Current room is $roomId - You are the caller!';
+ // Created a Room
+
+ peerConnection?.onTrack = (RTCTrackEvent event) {
+ print('Got remote track: ${event.streams[0]}');
+
+ event.streams[0].getTracks().forEach((track) {
+ print('Add a track to the remoteStream $track');
+ remoteStream?.addTrack(track);
+ });
+ };
+
+ // Listening for remote session description below
+ roomRef.snapshots().listen((snapshot) async {
+ print('Got updated room: ${snapshot.data()}');
+
+ Map data = snapshot.data() as Map;
+ if (peerConnection?.getRemoteDescription() != null && data['answer'] != null) {
+ var answer = RTCSessionDescription(
+ data['answer']['sdp'],
+ data['answer']['type'],
+ );
+
+ print("Someone tried to connect");
+ await peerConnection?.setRemoteDescription(answer);
+ }
+ });
+ // Listening for remote session description above
+
+ // Listen for remote Ice candidates below
+ roomRef.collection('calleeCandidates').snapshots().listen((snapshot) {
+ snapshot.docChanges.forEach((change) {
+ if (change.type == DocumentChangeType.added) {
+ Map data = change.doc.data() as Map;
+ print('Got new remote ICE candidate: ${jsonEncode(data)}');
+ peerConnection.addCandidate(
+ RTCIceCandidate(
+ data['candidate'],
+ data['sdpMid'],
+ data['sdpMLineIndex'],
+ ),
+ );
+ }
+ });
+ });
+ // Listen for remote ICE candidates above
+
+ return roomId;
+ }
+
+ Future joinRoom(String roomId, RTCVideoRenderer remoteVideo) async {
+ FirebaseFirestore db = FirebaseFirestore.instance;
+ DocumentReference roomRef = db.collection('rooms').doc('$roomId');
+ var roomSnapshot = await roomRef.get();
+ print('Got room ${roomSnapshot.exists}');
+
+ if (roomSnapshot.exists) {
+ print('Create PeerConnection with configuration: $configuration');
+ peerConnection = await createPeerConnection(configuration);
+
+ registerPeerConnectionListeners();
+
+ localStream.getTracks().forEach((track) {
+ peerConnection?.addTrack(track, localStream);
+ });
+
+ // Code for collecting ICE candidates below
+ var calleeCandidatesCollection = roomRef.collection('calleeCandidates');
+ peerConnection.onIceCandidate = (RTCIceCandidate candidate) {
+ if (candidate == null) {
+ print('onIceCandidate: complete!');
+ return;
+ }
+ print('onIceCandidate: ${candidate.toMap()}');
+ calleeCandidatesCollection.add(candidate.toMap());
+ };
+ // Code for collecting ICE candidate above
+
+ peerConnection?.onTrack = (RTCTrackEvent event) {
+ print('Got remote track: ${event.streams[0]}');
+ event.streams[0].getTracks().forEach((track) {
+ print('Add a track to the remoteStream: $track');
+ remoteStream?.addTrack(track);
+ });
+ };
+
+ // Code for creating SDP answer below
+ var data = roomSnapshot.data() as Map;
+ print('Got offer $data');
+ var offer = data['offer'];
+ await peerConnection?.setRemoteDescription(
+ RTCSessionDescription(offer['sdp'], offer['type']),
+ );
+ var answer = await peerConnection.createAnswer();
+ print('Created Answer $answer');
+
+ await peerConnection.setLocalDescription(answer);
+
+ Map roomWithAnswer = {
+ 'answer': {'type': answer.type, 'sdp': answer.sdp}
+ };
+
+ await roomRef.update(roomWithAnswer);
+ // Finished creating SDP answer
+
+ // Listening for remote ICE candidates below
+ // roomRef.collection('callerCandidates').snapshots().listen((snapshot) {
+ // snapshot.docChanges.forEach((document) {
+ // var data = document.doc.data() as Map;
+ // print(data);
+ // print('Got new remote ICE candidate: $data');
+ // peerConnection.addCandidate(
+ // RTCIceCandidate(
+ // data['candidate'],
+ // data['sdpMid'],
+ // data['sdpMLineIndex'],
+ // ),
+ // );
+ // });
+ // });
+ }
+ }
+
+ Future openUserMedia(
+ RTCVideoRenderer localVideo,
+ RTCVideoRenderer remoteVideo,
+ ) async {
+ var stream = await navigator.mediaDevices.getUserMedia({'video': true, 'audio': false});
+
+ localVideo.srcObject = stream;
+ localStream = stream;
+
+ remoteVideo.srcObject = await createLocalMediaStream('key');
+ }
+
+ Future hangUp(RTCVideoRenderer localVideo) async {
+ List tracks = localVideo.srcObject.getTracks();
+ tracks.forEach((track) {
+ track.stop();
+ });
+
+ if (remoteStream != null) {
+ remoteStream.getTracks().forEach((track) => track.stop());
+ }
+ if (peerConnection != null) peerConnection.close();
+
+ if (roomId != null) {
+ var db = FirebaseFirestore.instance;
+ var roomRef = db.collection('rooms').doc(roomId);
+ var calleeCandidates = await roomRef.collection('calleeCandidates').get();
+ calleeCandidates.docs.forEach((document) => document.reference.delete());
+
+ var callerCandidates = await roomRef.collection('callerCandidates').get();
+ callerCandidates.docs.forEach((document) => document.reference.delete());
+
+ await roomRef.delete();
+ }
+
+ localStream.dispose();
+ remoteStream?.dispose();
+ }
+
+ void registerPeerConnectionListeners() {
+ peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
+ print('ICE gathering state changed: $state');
+ };
+
+ peerConnection?.onConnectionState = (RTCPeerConnectionState state) {
+ print('Connection state change: $state');
+ };
+
+ peerConnection?.onSignalingState = (RTCSignalingState state) {
+ print('Signaling state change: $state');
+ };
+
+ peerConnection?.onIceGatheringState = (RTCIceGatheringState state) {
+ print('ICE connection state change: $state');
+ };
+
+ peerConnection?.onAddStream = (MediaStream stream) {
+ print("Add remote stream");
+ onAddRemoteStream?.call(stream);
+ remoteStream = stream;
+ };
+ }
+}
diff --git a/lib/routes.dart b/lib/routes.dart
index 72599bb2..9525bc96 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -21,6 +21,8 @@ import 'package:diplomaticquarterapp/pages/symptom-checker/info.dart';
import 'package:diplomaticquarterapp/pages/symptom-checker/select-gender.dart';
import 'package:diplomaticquarterapp/pages/symptom-checker/symtom-checker.dart';
import 'package:diplomaticquarterapp/pages/webRTC/OpenTok/OpenTok.dart';
+import 'package:diplomaticquarterapp/pages/webRTC/call_page.dart';
+import 'package:diplomaticquarterapp/pages/webRTC/call_page_bkp.dart';
import 'package:diplomaticquarterapp/splashPage.dart';
const String INIT_ROUTE = '/';
@@ -48,6 +50,7 @@ const String PACKAGES_ORDER_COMPLETED = 'packages-offers-cart';
const String TEST_PAGE = 'test-page';
const String OPENTOK_CALL_PAGE = 'OPENTOK_CALL_PAGE';
const String CART_ORDER_PAGE = 'cart-order-page';
+const String CALL_PAGE = 'CALL_PAGE';
const String HEALTH_WEATHER = 'health-weather';
const APP_UPDATE = 'app-update';
@@ -76,6 +79,7 @@ var routes = {
APP_UPDATE: (_) => AppUpdatePage(),
SETTINGS: (_) => Settings(),
CART_ORDER_PAGE: (_) => CartOrderPage(),
+ CALL_PAGE: (_) => CallPage(),
OPENTOK_CALL_PAGE: (_) => OpenTokConnectCallPage(
apiKey: '46209962',
sessionId: '1_MX40NjIwOTk2Mn5-MTYzNDY0ODM3NDY2Nn5PcnpnNGM0R1Q3ODZ6UXlFQ01lMDF5YWJ-fg',
diff --git a/lib/uitl/PlatformBridge.dart b/lib/uitl/PlatformBridge.dart
index 56020781..45970e5e 100644
--- a/lib/uitl/PlatformBridge.dart
+++ b/lib/uitl/PlatformBridge.dart
@@ -1,4 +1,3 @@
-
import 'package:diplomaticquarterapp/config/config.dart';
import 'package:diplomaticquarterapp/config/localized_values.dart';
import 'package:diplomaticquarterapp/config/shared_pref_kay.dart';
@@ -89,6 +88,9 @@ class PlatformBridge {
static const show_loading_method = "loading";
static const register_Hmg_Geofences = "registerHmgGeofences";
static const un_register_Hmg_Geofences = "unRegisterHmgGeofences";
+ static const IS_DRAW_OVER_APPS_PERMISSION_ALLOWED = "isDrawOverAppsPermissionAllowed";
+ static const ASK_DRAW_OVER_APPS_PERMISSION = "askDrawOverAppsPermission";
+ static const GET_INTENT = "getIntent";
Future