Merge branch 'development' into 'master'
New Services Live care Video call and others See merge request Cloud_Solution/doctor_app_flutter!768merge-requests/776/merge
@ -1,15 +0,0 @@
|
|||||||
package com.example.doctor_app_flutter.Service;
|
|
||||||
|
|
||||||
import com.example.doctor_app_flutter.Model.GetSessionStatusModel;
|
|
||||||
import com.example.doctor_app_flutter.Model.SessionStatusModel;
|
|
||||||
|
|
||||||
|
|
||||||
import retrofit2.Call;
|
|
||||||
import retrofit2.http.Body;
|
|
||||||
import retrofit2.http.POST;
|
|
||||||
|
|
||||||
public interface SessionStatusAPI {
|
|
||||||
|
|
||||||
@POST("LiveCareApi/DoctorApp/GetSessionStatus")
|
|
||||||
Call<SessionStatusModel> getSessionStatusModelData(@Body GetSessionStatusModel getSessionStatusModel);
|
|
||||||
}
|
|
||||||
@ -1,430 +0,0 @@
|
|||||||
package com.example.doctor_app_flutter.ui;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.CountDownTimer;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.example.doctor_app_flutter.Model.GetSessionStatusModel;
|
|
||||||
import com.example.doctor_app_flutter.Model.SessionStatusModel;
|
|
||||||
import com.hmg.hmgDr.R;
|
|
||||||
import com.opentok.android.Session;
|
|
||||||
import com.opentok.android.Stream;
|
|
||||||
import com.opentok.android.Publisher;
|
|
||||||
import com.opentok.android.PublisherKit;
|
|
||||||
import com.opentok.android.Subscriber;
|
|
||||||
import com.opentok.android.BaseVideoRenderer;
|
|
||||||
import com.opentok.android.OpentokError;
|
|
||||||
import com.opentok.android.SubscriberKit;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import pub.devrel.easypermissions.AfterPermissionGranted;
|
|
||||||
import pub.devrel.easypermissions.AppSettingsDialog;
|
|
||||||
import pub.devrel.easypermissions.EasyPermissions;
|
|
||||||
|
|
||||||
public class VideoCallActivity extends AppCompatActivity implements EasyPermissions.PermissionCallbacks,
|
|
||||||
Session.SessionListener,
|
|
||||||
Publisher.PublisherListener,
|
|
||||||
Subscriber.VideoListener, VideoCallContract.VideoCallView {
|
|
||||||
|
|
||||||
private static final String TAG = VideoCallActivity.class.getSimpleName();
|
|
||||||
|
|
||||||
VideoCallContract.VideoCallPresenter videoCallPresenter;
|
|
||||||
|
|
||||||
private static final int RC_SETTINGS_SCREEN_PERM = 123;
|
|
||||||
private static final int RC_VIDEO_APP_PERM = 124;
|
|
||||||
|
|
||||||
|
|
||||||
private Session mSession;
|
|
||||||
private Publisher mPublisher;
|
|
||||||
private Subscriber mSubscriber;
|
|
||||||
|
|
||||||
private Handler mVolHandler, mConnectedHandler;
|
|
||||||
private Runnable mVolRunnable, mConnectedRunnable;
|
|
||||||
|
|
||||||
private FrameLayout mPublisherViewContainer;
|
|
||||||
private RelativeLayout mSubscriberViewContainer;
|
|
||||||
private RelativeLayout controlPanel;
|
|
||||||
|
|
||||||
private String apiKey;
|
|
||||||
private String sessionId;
|
|
||||||
private String token;
|
|
||||||
private String appLang;
|
|
||||||
private String baseUrl;
|
|
||||||
|
|
||||||
private boolean isSwitchCameraClicked;
|
|
||||||
private boolean isCameraClicked;
|
|
||||||
private boolean isSpeckerClicked;
|
|
||||||
private boolean isMicClicked;
|
|
||||||
|
|
||||||
private ImageView mCallBtn;
|
|
||||||
private ImageView mCameraBtn;
|
|
||||||
private ImageView mSwitchCameraBtn;
|
|
||||||
private ImageView mspeckerBtn;
|
|
||||||
private ImageView mMicBtn;
|
|
||||||
|
|
||||||
private ProgressBar progressBar;
|
|
||||||
private CountDownTimer countDownTimer;
|
|
||||||
private TextView progressBarTextView;
|
|
||||||
private RelativeLayout progressBarLayout;
|
|
||||||
|
|
||||||
private boolean isConnected = false;
|
|
||||||
|
|
||||||
private GetSessionStatusModel sessionStatusModel;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
setTheme(R.style.AppTheme);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_video_call);
|
|
||||||
Objects.requireNonNull(getSupportActionBar()).hide();
|
|
||||||
initUI();
|
|
||||||
requestPermissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
|
|
||||||
if (mSession == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mSession.onPause();
|
|
||||||
|
|
||||||
if (isFinishing()) {
|
|
||||||
disconnectSession();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
if (mSession == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mSession.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
disconnectSession();
|
|
||||||
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
private void initUI() {
|
|
||||||
mPublisherViewContainer = (FrameLayout) findViewById(R.id.local_video_view_container);
|
|
||||||
mSubscriberViewContainer = (RelativeLayout) findViewById(R.id.remote_video_view_container);
|
|
||||||
|
|
||||||
apiKey = getIntent().getStringExtra("apiKey");
|
|
||||||
sessionId = getIntent().getStringExtra("sessionId");
|
|
||||||
token = getIntent().getStringExtra("token");
|
|
||||||
appLang = getIntent().getStringExtra("appLang");
|
|
||||||
baseUrl = getIntent().getStringExtra("baseUrl");
|
|
||||||
sessionStatusModel = getIntent().getParcelableExtra("sessionStatusModel");
|
|
||||||
|
|
||||||
controlPanel = findViewById(R.id.control_panel);
|
|
||||||
|
|
||||||
videoCallPresenter = new VideoCallPresenterImpl(this, baseUrl);
|
|
||||||
|
|
||||||
|
|
||||||
mCallBtn = findViewById(R.id.btn_call);
|
|
||||||
mCameraBtn = findViewById(R.id.btn_camera);
|
|
||||||
mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);
|
|
||||||
mspeckerBtn = findViewById(R.id.btn_specker);
|
|
||||||
mMicBtn = findViewById(R.id.btn_mic);
|
|
||||||
|
|
||||||
// progressBarLayout=findViewById(R.id.progressBar);
|
|
||||||
// progressBar=findViewById(R.id.progress_bar);
|
|
||||||
// progressBarTextView=findViewById(R.id.progress_bar_text);
|
|
||||||
// progressBar.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
hiddenButtons();
|
|
||||||
|
|
||||||
checkClientConnected();
|
|
||||||
|
|
||||||
mSubscriberViewContainer.setOnTouchListener((v, event) -> {
|
|
||||||
controlPanel.setVisibility(View.VISIBLE);
|
|
||||||
mVolHandler.removeCallbacks(mVolRunnable);
|
|
||||||
mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (appLang.equals("ar")) {
|
|
||||||
progressBarLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkClientConnected() {
|
|
||||||
mConnectedHandler = new Handler();
|
|
||||||
mConnectedRunnable = () -> {
|
|
||||||
if (!isConnected) {
|
|
||||||
videoCallPresenter.callClintConnected(sessionStatusModel);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mConnectedHandler.postDelayed(mConnectedRunnable, 30 * 1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hiddenButtons() {
|
|
||||||
mVolHandler = new Handler();
|
|
||||||
mVolRunnable = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
controlPanel.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mVolHandler.postDelayed(mVolRunnable, 5 * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
|
|
||||||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPermissionsGranted(int requestCode, List<String> perms) {
|
|
||||||
Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPermissionsDenied(int requestCode, List<String> perms) {
|
|
||||||
Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
|
|
||||||
|
|
||||||
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
|
|
||||||
new AppSettingsDialog.Builder(this)
|
|
||||||
.setTitle(getString(R.string.title_settings_dialog))
|
|
||||||
.setRationale(getString(R.string.rationale_ask_again))
|
|
||||||
.setPositiveButton(getString(R.string.setting))
|
|
||||||
.setNegativeButton(getString(R.string.cancel))
|
|
||||||
.setRequestCode(RC_SETTINGS_SCREEN_PERM)
|
|
||||||
.build()
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterPermissionGranted(RC_VIDEO_APP_PERM)
|
|
||||||
private void requestPermissions() {
|
|
||||||
String[] perms = {Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
|
|
||||||
if (EasyPermissions.hasPermissions(this, perms)) {
|
|
||||||
mSession = new Session.Builder(VideoCallActivity.this, apiKey, sessionId).build();
|
|
||||||
mSession.setSessionListener(this);
|
|
||||||
mSession.connect(token);
|
|
||||||
} else {
|
|
||||||
EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, perms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnected(Session session) {
|
|
||||||
Log.i(TAG, "Session Connected");
|
|
||||||
|
|
||||||
mPublisher = new Publisher.Builder(this).build();
|
|
||||||
mPublisher.setPublisherListener(this);
|
|
||||||
|
|
||||||
mPublisherViewContainer.addView(mPublisher.getView());
|
|
||||||
|
|
||||||
if (mPublisher.getView() instanceof GLSurfaceView) {
|
|
||||||
((GLSurfaceView) mPublisher.getView()).setZOrderOnTop(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
mSession.publish(mPublisher);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisconnected(Session session) {
|
|
||||||
Log.d(TAG, "onDisconnected: disconnected from session " + session.getSessionId());
|
|
||||||
|
|
||||||
mSession = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Session session, OpentokError opentokError) {
|
|
||||||
Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in session " + session.getSessionId());
|
|
||||||
|
|
||||||
Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStreamReceived(Session session, Stream stream) {
|
|
||||||
Log.d(TAG, "onStreamReceived: New stream " + stream.getStreamId() + " in session " + session.getSessionId());
|
|
||||||
if (mSubscriber != null) {
|
|
||||||
isConnected = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isConnected = true;
|
|
||||||
subscribeToStream(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStreamDropped(Session session, Stream stream) {
|
|
||||||
Log.d(TAG, "onStreamDropped: Stream " + stream.getStreamId() + " dropped from session " + session.getSessionId());
|
|
||||||
|
|
||||||
if (mSubscriber == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSubscriber.getStream().equals(stream)) {
|
|
||||||
mSubscriberViewContainer.removeView(mSubscriber.getView());
|
|
||||||
mSubscriber.destroy();
|
|
||||||
mSubscriber = null;
|
|
||||||
}
|
|
||||||
disconnectSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStreamCreated(PublisherKit publisherKit, Stream stream) {
|
|
||||||
Log.d(TAG, "onStreamCreated: Own stream " + stream.getStreamId() + " created");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStreamDestroyed(PublisherKit publisherKit, Stream stream) {
|
|
||||||
Log.d(TAG, "onStreamDestroyed: Own stream " + stream.getStreamId() + " destroyed");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(PublisherKit publisherKit, OpentokError opentokError) {
|
|
||||||
Log.d(TAG, "onError: Error (" + opentokError.getMessage() + ") in publisher");
|
|
||||||
|
|
||||||
Toast.makeText(this, "Session error. See the logcat please.", Toast.LENGTH_LONG).show();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoDataReceived(SubscriberKit subscriberKit) {
|
|
||||||
mSubscriber.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL);
|
|
||||||
mSubscriberViewContainer.addView(mSubscriber.getView());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoDisabled(SubscriberKit subscriberKit, String s) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoEnabled(SubscriberKit subscriberKit, String s) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoDisableWarning(SubscriberKit subscriberKit) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onVideoDisableWarningLifted(SubscriberKit subscriberKit) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void subscribeToStream(Stream stream) {
|
|
||||||
mSubscriber = new Subscriber.Builder(VideoCallActivity.this, stream).build();
|
|
||||||
mSubscriber.setVideoListener(this);
|
|
||||||
mSession.subscribe(mSubscriber);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void disconnectSession() {
|
|
||||||
if (mSession == null) {
|
|
||||||
setResult(Activity.RESULT_CANCELED);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mSubscriber != null) {
|
|
||||||
mSubscriberViewContainer.removeView(mSubscriber.getView());
|
|
||||||
mSession.unsubscribe(mSubscriber);
|
|
||||||
mSubscriber.destroy();
|
|
||||||
mSubscriber = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPublisher != null) {
|
|
||||||
mPublisherViewContainer.removeView(mPublisher.getView());
|
|
||||||
mSession.unpublish(mPublisher);
|
|
||||||
mPublisher.destroy();
|
|
||||||
mPublisher = null;
|
|
||||||
}
|
|
||||||
mSession.disconnect();
|
|
||||||
if (countDownTimer != null) {
|
|
||||||
countDownTimer.cancel();
|
|
||||||
}
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSwitchCameraClicked(View view) {
|
|
||||||
if (mPublisher != null) {
|
|
||||||
isSwitchCameraClicked = !isSwitchCameraClicked;
|
|
||||||
mPublisher.cycleCamera();
|
|
||||||
int res = isSwitchCameraClicked ? R.drawable.flip_disapled : R.drawable.flip_enabled;
|
|
||||||
mSwitchCameraBtn.setImageResource(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCameraClicked(View view) {
|
|
||||||
if (mPublisher != null) {
|
|
||||||
isCameraClicked = !isCameraClicked;
|
|
||||||
mPublisher.setPublishVideo(!isCameraClicked);
|
|
||||||
int res = isCameraClicked ? R.drawable.video_disanabled : R.drawable.video_enabled;
|
|
||||||
mCameraBtn.setImageResource(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onSpeckerClicked(View view) {
|
|
||||||
if (mSubscriber != null) {
|
|
||||||
isSpeckerClicked = !isSpeckerClicked;
|
|
||||||
mSubscriber.setSubscribeToAudio(!isSpeckerClicked);
|
|
||||||
int res = isSpeckerClicked ? R.drawable.audio_disabled : R.drawable.audio_enabled;
|
|
||||||
mspeckerBtn.setImageResource(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onMicClicked(View view) {
|
|
||||||
|
|
||||||
if (mPublisher != null) {
|
|
||||||
isMicClicked = !isMicClicked;
|
|
||||||
mPublisher.setPublishAudio(!isMicClicked);
|
|
||||||
int res = isMicClicked ? R.drawable.mic_disabled : R.drawable.mic_enabled;
|
|
||||||
mMicBtn.setImageResource(res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCallClicked(View view) {
|
|
||||||
disconnectSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCallSuccessful(SessionStatusModel sessionStatusModel) {
|
|
||||||
if (sessionStatusModel.getSessionStatus() == 2 || sessionStatusModel.getSessionStatus() == 3) {
|
|
||||||
Intent returnIntent = new Intent();
|
|
||||||
returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel);
|
|
||||||
setResult(Activity.RESULT_OK, returnIntent);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
package com.example.doctor_app_flutter.ui;
|
|
||||||
|
|
||||||
import com.example.doctor_app_flutter.Model.GetSessionStatusModel;
|
|
||||||
import com.example.doctor_app_flutter.Model.SessionStatusModel;
|
|
||||||
|
|
||||||
public interface VideoCallContract {
|
|
||||||
|
|
||||||
interface VideoCallView{
|
|
||||||
|
|
||||||
void onCallSuccessful(SessionStatusModel sessionStatusModel);
|
|
||||||
void onFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
interface VideoCallPresenter {
|
|
||||||
|
|
||||||
void callClintConnected(GetSessionStatusModel statusModel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,137 @@
|
|||||||
|
package com.hmg.hmgDr.Model;
|
||||||
|
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
|
||||||
|
public class ChangeCallStatusRequestModel implements Parcelable {
|
||||||
|
|
||||||
|
@SerializedName("CallStatus")
|
||||||
|
@Expose
|
||||||
|
private Integer callStatus;
|
||||||
|
@SerializedName("DoctorId")
|
||||||
|
@Expose
|
||||||
|
private Integer doctorId;
|
||||||
|
@SerializedName("generalid")
|
||||||
|
@Expose
|
||||||
|
private String generalid;
|
||||||
|
@SerializedName("TokenID")
|
||||||
|
@Expose
|
||||||
|
private String tokenID;
|
||||||
|
@SerializedName("VC_ID")
|
||||||
|
@Expose
|
||||||
|
private Integer vcId;
|
||||||
|
|
||||||
|
public ChangeCallStatusRequestModel(Integer callStatus, Integer doctorId, String generalid, String tokenID, Integer vcId) {
|
||||||
|
this.callStatus = callStatus;
|
||||||
|
this.doctorId = doctorId;
|
||||||
|
this.generalid = generalid;
|
||||||
|
this.tokenID = tokenID;
|
||||||
|
this.vcId = vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ChangeCallStatusRequestModel(Parcel in) {
|
||||||
|
if (in.readByte() == 0) {
|
||||||
|
callStatus = null;
|
||||||
|
} else {
|
||||||
|
callStatus = in.readInt();
|
||||||
|
}
|
||||||
|
if (in.readByte() == 0) {
|
||||||
|
doctorId = null;
|
||||||
|
} else {
|
||||||
|
doctorId = in.readInt();
|
||||||
|
}
|
||||||
|
generalid = in.readString();
|
||||||
|
tokenID = in.readString();
|
||||||
|
if (in.readByte() == 0) {
|
||||||
|
vcId = null;
|
||||||
|
} else {
|
||||||
|
vcId = in.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<ChangeCallStatusRequestModel> CREATOR = new Creator<ChangeCallStatusRequestModel>() {
|
||||||
|
@Override
|
||||||
|
public ChangeCallStatusRequestModel createFromParcel(Parcel in) {
|
||||||
|
return new ChangeCallStatusRequestModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChangeCallStatusRequestModel[] newArray(int size) {
|
||||||
|
return new ChangeCallStatusRequestModel[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public Integer getCallStatus() {
|
||||||
|
return callStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallStatus(Integer callStatus) {
|
||||||
|
this.callStatus = callStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getDoctorId() {
|
||||||
|
return doctorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoctorId(Integer doctorId) {
|
||||||
|
this.doctorId = doctorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGeneralid() {
|
||||||
|
return generalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGeneralid(String generalid) {
|
||||||
|
this.generalid = generalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenID() {
|
||||||
|
return tokenID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenID(String tokenID) {
|
||||||
|
this.tokenID = tokenID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getVcId() {
|
||||||
|
return vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVcId(Integer vcId) {
|
||||||
|
this.vcId = vcId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
if (callStatus == null) {
|
||||||
|
dest.writeByte((byte) 0);
|
||||||
|
} else {
|
||||||
|
dest.writeByte((byte) 1);
|
||||||
|
dest.writeInt(callStatus);
|
||||||
|
}
|
||||||
|
if (doctorId == null) {
|
||||||
|
dest.writeByte((byte) 0);
|
||||||
|
} else {
|
||||||
|
dest.writeByte((byte) 1);
|
||||||
|
dest.writeInt(doctorId);
|
||||||
|
}
|
||||||
|
dest.writeString(generalid);
|
||||||
|
dest.writeString(tokenID);
|
||||||
|
if (vcId == null) {
|
||||||
|
dest.writeByte((byte) 0);
|
||||||
|
} else {
|
||||||
|
dest.writeByte((byte) 1);
|
||||||
|
dest.writeInt(vcId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.example.doctor_app_flutter.Model;
|
package com.hmg.hmgDr.Model;
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.example.doctor_app_flutter.Service;
|
package com.hmg.hmgDr.Service;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.hmg.hmgDr.Service;
|
||||||
|
|
||||||
|
import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
|
||||||
|
import com.hmg.hmgDr.Model.GetSessionStatusModel;
|
||||||
|
import com.hmg.hmgDr.Model.SessionStatusModel;
|
||||||
|
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Body;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
|
||||||
|
public interface SessionStatusAPI {
|
||||||
|
|
||||||
|
@POST("LiveCareApi/DoctorApp/GetSessionStatus")
|
||||||
|
Call<SessionStatusModel> getSessionStatusModelData(@Body GetSessionStatusModel getSessionStatusModel);
|
||||||
|
|
||||||
|
@POST("LiveCareApi/DoctorApp/ChangeCallStatus")
|
||||||
|
Call<SessionStatusModel> changeCallStatus(@Body ChangeCallStatusRequestModel changeCallStatusRequestModel);
|
||||||
|
}
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
package com.hmg.hmgDr.Service
|
||||||
|
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Binder
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.IBinder
|
||||||
|
import com.hmg.hmgDr.MainActivity
|
||||||
|
import com.hmg.hmgDr.ui.VideoCallResponseListener
|
||||||
|
import com.hmg.hmgDr.ui.fragment.VideoCallFragment
|
||||||
|
|
||||||
|
class VideoStreamContainerService : Service(), VideoCallResponseListener {
|
||||||
|
|
||||||
|
var videoCallResponseListener: VideoCallResponseListener? = null
|
||||||
|
var mActivity: MainActivity? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
if (field != null) {
|
||||||
|
setDialogFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var arguments: Bundle? = null
|
||||||
|
var serviceRunning: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
|
private val serviceBinder: IBinder = VideoStreamBinder()
|
||||||
|
private var dialogFragment: VideoCallFragment? = null
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder {
|
||||||
|
return serviceBinder
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setDialogFragment() {
|
||||||
|
mActivity?.run {
|
||||||
|
if (dialogFragment == null) {
|
||||||
|
val transaction = supportFragmentManager.beginTransaction()
|
||||||
|
dialogFragment = VideoCallFragment.newInstance(arguments!!)
|
||||||
|
dialogFragment?.let {
|
||||||
|
it.setCallListener(this@VideoStreamContainerService)
|
||||||
|
it.isCancelable = true
|
||||||
|
if (it.isAdded) {
|
||||||
|
it.dismiss()
|
||||||
|
} else {
|
||||||
|
it.show(transaction, "dialog")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!dialogFragment!!.isVisible) {
|
||||||
|
val transaction = supportFragmentManager.beginTransaction()
|
||||||
|
dialogFragment!!.show(transaction, "dialog")
|
||||||
|
} else {
|
||||||
|
// don't do anything
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeVideoCall(){
|
||||||
|
dialogFragment?.onCallClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
if (intent != null && intent.extras != null) {
|
||||||
|
arguments = intent.extras
|
||||||
|
}
|
||||||
|
// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show()
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
// Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class VideoStreamBinder : Binder() {
|
||||||
|
val service: VideoStreamContainerService
|
||||||
|
get() = this@VideoStreamContainerService
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCallFinished(resultCode: Int, intent: Intent?) {
|
||||||
|
dialogFragment = null
|
||||||
|
videoCallResponseListener?.onCallFinished(resultCode, intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun errorHandle(message: String) {
|
||||||
|
dialogFragment = null
|
||||||
|
// Toast.makeText(this, message, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun minimizeVideoEvent(isMinimize: Boolean) {
|
||||||
|
videoCallResponseListener?.minimizeVideoEvent(isMinimize)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.hmg.hmgDr.ui;
|
||||||
|
|
||||||
|
import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
|
||||||
|
import com.hmg.hmgDr.Model.GetSessionStatusModel;
|
||||||
|
import com.hmg.hmgDr.Model.SessionStatusModel;
|
||||||
|
|
||||||
|
public interface VideoCallContract {
|
||||||
|
|
||||||
|
interface VideoCallView {
|
||||||
|
|
||||||
|
void onCallSuccessful(SessionStatusModel sessionStatusModel);
|
||||||
|
|
||||||
|
void onCallChangeCallStatusSuccessful(SessionStatusModel sessionStatusModel);
|
||||||
|
|
||||||
|
void onFailure();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface VideoCallPresenter {
|
||||||
|
|
||||||
|
void callClintConnected(GetSessionStatusModel statusModel);
|
||||||
|
|
||||||
|
void callChangeCallStatus(ChangeCallStatusRequestModel statusModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.hmg.hmgDr.ui
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
|
||||||
|
interface VideoCallResponseListener {
|
||||||
|
|
||||||
|
fun onCallFinished(resultCode : Int, intent: Intent? = null)
|
||||||
|
|
||||||
|
fun errorHandle(message: String){}
|
||||||
|
|
||||||
|
fun minimizeVideoEvent(isMinimize : Boolean)
|
||||||
|
|
||||||
|
fun onBackHandle(){}
|
||||||
|
}
|
||||||
@ -0,0 +1,379 @@
|
|||||||
|
package com.hmg.hmgDr.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
import android.opengl.GLES20
|
||||||
|
import android.opengl.GLSurfaceView
|
||||||
|
import android.opengl.Matrix
|
||||||
|
import android.view.View
|
||||||
|
import com.opentok.android.BaseVideoRenderer
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.nio.FloatBuffer
|
||||||
|
import java.nio.ShortBuffer
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig
|
||||||
|
import javax.microedition.khronos.opengles.GL10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* https://nhancv.medium.com/android-how-to-make-a-circular-view-as-a-thumbnail-of-opentok-27992aee15c9
|
||||||
|
* to solve make circle video stream
|
||||||
|
* */
|
||||||
|
|
||||||
|
class DynamicVideoRenderer(private val mContext: Context) : BaseVideoRenderer() {
|
||||||
|
private val mView: GLSurfaceView = GLSurfaceView(mContext)
|
||||||
|
private val mRenderer: MyRenderer
|
||||||
|
|
||||||
|
interface DynamicVideoRendererMetadataListener {
|
||||||
|
fun onMetadataReady(metadata: ByteArray?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setDynamicVideoRendererMetadataListener(metadataListener: DynamicVideoRendererMetadataListener?) {
|
||||||
|
mRenderer.metadataListener = metadataListener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableThumbnailCircle(enable: Boolean) {
|
||||||
|
mRenderer.requestEnableThumbnailCircle = enable
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MyRenderer : GLSurfaceView.Renderer {
|
||||||
|
var mTextureIds = IntArray(3)
|
||||||
|
var mScaleMatrix = FloatArray(16)
|
||||||
|
private val mVertexBuffer: FloatBuffer
|
||||||
|
private val mTextureBuffer: FloatBuffer
|
||||||
|
private val mDrawListBuffer: ShortBuffer
|
||||||
|
var requestEnableThumbnailCircle = false
|
||||||
|
var mVideoFitEnabled = true
|
||||||
|
var mVideoDisabled = false
|
||||||
|
private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition;
|
||||||
|
attribute vec2 aTextureCoord;
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
void main() {
|
||||||
|
gl_Position = uMVPMatrix * aPosition;
|
||||||
|
vTextureCoord = aTextureCoord;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
private val fragmentShaderCode = """precision mediump float;
|
||||||
|
uniform sampler2D Ytex;
|
||||||
|
uniform sampler2D Utex,Vtex;
|
||||||
|
uniform int enableCircle;
|
||||||
|
uniform vec2 radiusDp;
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
void main(void) {
|
||||||
|
float nx,ny,r,g,b,y,u,v;
|
||||||
|
mediump vec4 txl,ux,vx; nx=vTextureCoord[0];
|
||||||
|
ny=vTextureCoord[1];
|
||||||
|
y=texture2D(Ytex,vec2(nx,ny)).r;
|
||||||
|
u=texture2D(Utex,vec2(nx,ny)).r;
|
||||||
|
v=texture2D(Vtex,vec2(nx,ny)).r;
|
||||||
|
y=1.1643*(y-0.0625);
|
||||||
|
u=u-0.5;
|
||||||
|
v=v-0.5;
|
||||||
|
r=y+1.5958*v;
|
||||||
|
g=y-0.39173*u-0.81290*v;
|
||||||
|
b=y+2.017*u;
|
||||||
|
if (enableCircle > 0) {
|
||||||
|
float radius = 0.5;
|
||||||
|
vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
vec4 color1 = vec4(r, g, b, 1.0);
|
||||||
|
vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5));
|
||||||
|
float t = 1.0;
|
||||||
|
if (dist < 0.0) t = 0.0;
|
||||||
|
gl_FragColor = mix(color0, color1, t);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gl_FragColor = vec4(r, g, b, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
var mFrameLock = ReentrantLock()
|
||||||
|
var mCurrentFrame: Frame? = null
|
||||||
|
private var mProgram = 0
|
||||||
|
private var mTextureWidth = 0
|
||||||
|
private var mTextureHeight = 0
|
||||||
|
private var mViewportWidth = 0
|
||||||
|
private var mViewportHeight = 0
|
||||||
|
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 1f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
|
||||||
|
vertexShaderCode)
|
||||||
|
val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
|
||||||
|
fragmentShaderCode)
|
||||||
|
mProgram = GLES20.glCreateProgram() // create empty OpenGL ES
|
||||||
|
// Program
|
||||||
|
GLES20.glAttachShader(mProgram, vertexShader) // add the vertex
|
||||||
|
// shader to program
|
||||||
|
GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment
|
||||||
|
// shader to
|
||||||
|
// program
|
||||||
|
GLES20.glLinkProgram(mProgram)
|
||||||
|
val positionHandle = GLES20.glGetAttribLocation(mProgram,
|
||||||
|
"aPosition")
|
||||||
|
val textureHandle = GLES20.glGetAttribLocation(mProgram,
|
||||||
|
"aTextureCoord")
|
||||||
|
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
|
||||||
|
GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4,
|
||||||
|
mVertexBuffer)
|
||||||
|
GLES20.glEnableVertexAttribArray(positionHandle)
|
||||||
|
GLES20.glVertexAttribPointer(textureHandle,
|
||||||
|
TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
|
||||||
|
TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer)
|
||||||
|
GLES20.glEnableVertexAttribArray(textureHandle)
|
||||||
|
GLES20.glUseProgram(mProgram)
|
||||||
|
var i = GLES20.glGetUniformLocation(mProgram, "Ytex")
|
||||||
|
GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */
|
||||||
|
i = GLES20.glGetUniformLocation(mProgram, "Utex")
|
||||||
|
GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */
|
||||||
|
i = GLES20.glGetUniformLocation(mProgram, "Vtex")
|
||||||
|
GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */
|
||||||
|
val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp")
|
||||||
|
val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt()
|
||||||
|
GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat())
|
||||||
|
mTextureWidth = 0
|
||||||
|
mTextureHeight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableThumbnailCircle(enable: Boolean) {
|
||||||
|
GLES20.glUseProgram(mProgram)
|
||||||
|
val enableCircleLocation = GLES20.glGetUniformLocation(mProgram, "enableCircle")
|
||||||
|
GLES20.glUniform1i(enableCircleLocation, if (enable) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setupTextures(frame: Frame) {
|
||||||
|
if (mTextureIds[0] != 0) {
|
||||||
|
GLES20.glDeleteTextures(3, mTextureIds, 0)
|
||||||
|
}
|
||||||
|
GLES20.glGenTextures(3, mTextureIds, 0)
|
||||||
|
val w = frame.width
|
||||||
|
val h = frame.height
|
||||||
|
val hw = w + 1 shr 1
|
||||||
|
val hh = h + 1 shr 1
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h)
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh)
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh)
|
||||||
|
mTextureWidth = frame.width
|
||||||
|
mTextureHeight = frame.height
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateTextures(frame: Frame) {
|
||||||
|
val width = frame.width
|
||||||
|
val height = frame.height
|
||||||
|
val half_width = width + 1 shr 1
|
||||||
|
val half_height = height + 1 shr 1
|
||||||
|
val y_size = width * height
|
||||||
|
val uv_size = half_width * half_height
|
||||||
|
val bb = frame.buffer
|
||||||
|
// If we are reusing this frame, make sure we reset position and
|
||||||
|
// limit
|
||||||
|
bb.clear()
|
||||||
|
if (bb.remaining() == y_size + uv_size * 2) {
|
||||||
|
bb.position(0)
|
||||||
|
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1)
|
||||||
|
GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width,
|
||||||
|
height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
|
||||||
|
bb)
|
||||||
|
bb.position(y_size)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||||
|
half_width, half_height, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, bb)
|
||||||
|
bb.position(y_size + uv_size)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE2)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||||
|
half_width, half_height, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, bb)
|
||||||
|
} else {
|
||||||
|
mTextureWidth = 0
|
||||||
|
mTextureHeight = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
|
||||||
|
GLES20.glViewport(0, 0, width, height)
|
||||||
|
mViewportWidth = width
|
||||||
|
mViewportHeight = height
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadataListener: DynamicVideoRendererMetadataListener? = null
|
||||||
|
override fun onDrawFrame(gl: GL10) {
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 0f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
mFrameLock.lock()
|
||||||
|
if (mCurrentFrame != null && !mVideoDisabled) {
|
||||||
|
GLES20.glUseProgram(mProgram)
|
||||||
|
if (mTextureWidth != mCurrentFrame!!.width
|
||||||
|
|| mTextureHeight != mCurrentFrame!!.height) {
|
||||||
|
setupTextures(mCurrentFrame!!)
|
||||||
|
}
|
||||||
|
updateTextures(mCurrentFrame!!)
|
||||||
|
Matrix.setIdentityM(mScaleMatrix, 0)
|
||||||
|
var scaleX = 1.0f
|
||||||
|
var scaleY = 1.0f
|
||||||
|
val ratio = (mCurrentFrame!!.width.toFloat()
|
||||||
|
/ mCurrentFrame!!.height)
|
||||||
|
val vratio = mViewportWidth.toFloat() / mViewportHeight
|
||||||
|
if (mVideoFitEnabled) {
|
||||||
|
if (ratio > vratio) {
|
||||||
|
scaleY = vratio / ratio
|
||||||
|
} else {
|
||||||
|
scaleX = ratio / vratio
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ratio < vratio) {
|
||||||
|
scaleY = vratio / ratio
|
||||||
|
} else {
|
||||||
|
scaleX = ratio / vratio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Matrix.scaleM(mScaleMatrix, 0,
|
||||||
|
scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f,
|
||||||
|
scaleY, 1f)
|
||||||
|
metadataListener?.onMetadataReady(mCurrentFrame!!.metadata)
|
||||||
|
val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
|
||||||
|
"uMVPMatrix")
|
||||||
|
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
|
||||||
|
mScaleMatrix, 0)
|
||||||
|
enableThumbnailCircle(requestEnableThumbnailCircle)
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer)
|
||||||
|
} else {
|
||||||
|
//black frame when video is disabled
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 1f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayFrame(frame: Frame?) {
|
||||||
|
mFrameLock.lock()
|
||||||
|
if (mCurrentFrame != null) {
|
||||||
|
mCurrentFrame!!.recycle()
|
||||||
|
}
|
||||||
|
mCurrentFrame = frame
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disableVideo(b: Boolean) {
|
||||||
|
mFrameLock.lock()
|
||||||
|
mVideoDisabled = b
|
||||||
|
if (mVideoDisabled) {
|
||||||
|
if (mCurrentFrame != null) {
|
||||||
|
mCurrentFrame!!.recycle()
|
||||||
|
}
|
||||||
|
mCurrentFrame = null
|
||||||
|
}
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableVideoFit(enableVideoFit: Boolean) {
|
||||||
|
mVideoFitEnabled = enableVideoFit
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// number of coordinates per vertex in this array
|
||||||
|
const val COORDS_PER_VERTEX = 3
|
||||||
|
const val TEXTURECOORDS_PER_VERTEX = 2
|
||||||
|
var mXYZCoords = floatArrayOf(
|
||||||
|
-1.0f, 1.0f, 0.0f, // top left
|
||||||
|
-1.0f, -1.0f, 0.0f, // bottom left
|
||||||
|
1.0f, -1.0f, 0.0f, // bottom right
|
||||||
|
1.0f, 1.0f, 0.0f // top right
|
||||||
|
)
|
||||||
|
var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f)
|
||||||
|
fun initializeTexture(name: Int, id: Int, width: Int, height: Int) {
|
||||||
|
GLES20.glActiveTexture(name)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id)
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
|
||||||
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
|
||||||
|
width, height, 0, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadShader(type: Int, shaderCode: String?): Int {
|
||||||
|
val shader = GLES20.glCreateShader(type)
|
||||||
|
GLES20.glShaderSource(shader, shaderCode)
|
||||||
|
GLES20.glCompileShader(shader)
|
||||||
|
return shader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4)
|
||||||
|
bb.order(ByteOrder.nativeOrder())
|
||||||
|
mVertexBuffer = bb.asFloatBuffer()
|
||||||
|
mVertexBuffer.put(mXYZCoords)
|
||||||
|
mVertexBuffer.position(0)
|
||||||
|
val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4)
|
||||||
|
tb.order(ByteOrder.nativeOrder())
|
||||||
|
mTextureBuffer = tb.asFloatBuffer()
|
||||||
|
mTextureBuffer.put(mUVCoords)
|
||||||
|
mTextureBuffer.position(0)
|
||||||
|
val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2)
|
||||||
|
dlb.order(ByteOrder.nativeOrder())
|
||||||
|
mDrawListBuffer = dlb.asShortBuffer()
|
||||||
|
mDrawListBuffer.put(mVertexIndex)
|
||||||
|
mDrawListBuffer.position(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFrame(frame: Frame) {
|
||||||
|
mRenderer.displayFrame(frame)
|
||||||
|
mView.requestRender()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStyle(key: String, value: String) {
|
||||||
|
if (STYLE_VIDEO_SCALE == key) {
|
||||||
|
if (STYLE_VIDEO_FIT == value) {
|
||||||
|
mRenderer.enableVideoFit(true)
|
||||||
|
} else if (STYLE_VIDEO_FILL == value) {
|
||||||
|
mRenderer.enableVideoFit(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onVideoPropertiesChanged(videoEnabled: Boolean) {
|
||||||
|
mRenderer.disableVideo(!videoEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getView(): View {
|
||||||
|
return mView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
mView.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
mView.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val THUMBNAIL_SIZE = 90 //in dp
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
mView.setEGLContextClientVersion(2)
|
||||||
|
mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)
|
||||||
|
mView.holder.setFormat(PixelFormat.TRANSLUCENT)
|
||||||
|
mRenderer = MyRenderer()
|
||||||
|
mView.setRenderer(mRenderer)
|
||||||
|
mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,357 @@
|
|||||||
|
package com.hmg.hmgDr.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
import android.opengl.GLES20
|
||||||
|
import android.opengl.GLSurfaceView
|
||||||
|
import android.opengl.Matrix
|
||||||
|
import android.view.View
|
||||||
|
import com.opentok.android.BaseVideoRenderer
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
import java.nio.ByteOrder
|
||||||
|
import java.nio.FloatBuffer
|
||||||
|
import java.nio.ShortBuffer
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig
|
||||||
|
import javax.microedition.khronos.opengles.GL10
|
||||||
|
|
||||||
|
|
||||||
|
class ThumbnailCircleVideoRenderer(private val mContext: Context) : BaseVideoRenderer() {
|
||||||
|
private val mView: GLSurfaceView = GLSurfaceView(mContext)
|
||||||
|
private val mRenderer: MyRenderer
|
||||||
|
|
||||||
|
interface ThumbnailCircleVideoRendererMetadataListener {
|
||||||
|
fun onMetadataReady(metadata: ByteArray?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setThumbnailCircleVideoRendererMetadataListener(metadataListener: ThumbnailCircleVideoRendererMetadataListener?) {
|
||||||
|
mRenderer.metadataListener = metadataListener
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MyRenderer : GLSurfaceView.Renderer {
|
||||||
|
var mTextureIds = IntArray(3)
|
||||||
|
var mScaleMatrix = FloatArray(16)
|
||||||
|
private val mVertexBuffer: FloatBuffer
|
||||||
|
private val mTextureBuffer: FloatBuffer
|
||||||
|
private val mDrawListBuffer: ShortBuffer
|
||||||
|
var mVideoFitEnabled = true
|
||||||
|
var mVideoDisabled = false
|
||||||
|
private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition;
|
||||||
|
attribute vec2 aTextureCoord;
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
void main() {
|
||||||
|
gl_Position = uMVPMatrix * aPosition;
|
||||||
|
vTextureCoord = aTextureCoord;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
private val fragmentShaderCode = """precision mediump float;
|
||||||
|
uniform sampler2D Ytex;
|
||||||
|
uniform sampler2D Utex,Vtex;
|
||||||
|
uniform vec2 radiusDp;
|
||||||
|
varying vec2 vTextureCoord;
|
||||||
|
void main(void) {
|
||||||
|
float nx,ny,r,g,b,y,u,v;
|
||||||
|
mediump vec4 txl,ux,vx; nx=vTextureCoord[0];
|
||||||
|
ny=vTextureCoord[1];
|
||||||
|
y=texture2D(Ytex,vec2(nx,ny)).r;
|
||||||
|
u=texture2D(Utex,vec2(nx,ny)).r;
|
||||||
|
v=texture2D(Vtex,vec2(nx,ny)).r;
|
||||||
|
y=1.1643*(y-0.0625);
|
||||||
|
u=u-0.5;
|
||||||
|
v=v-0.5;
|
||||||
|
r=y+1.5958*v;
|
||||||
|
g=y-0.39173*u-0.81290*v;
|
||||||
|
b=y+2.017*u;
|
||||||
|
float radius = 0.5;
|
||||||
|
vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
|
vec4 color1 = vec4(r, g, b, 1.0);
|
||||||
|
vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5));
|
||||||
|
float t = 1.0;
|
||||||
|
if (dist < 0.0) t = 0.0;
|
||||||
|
gl_FragColor = mix(color0, color1, t);
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
var mFrameLock = ReentrantLock()
|
||||||
|
var mCurrentFrame: Frame? = null
|
||||||
|
private var mProgram = 0
|
||||||
|
private var mTextureWidth = 0
|
||||||
|
private var mTextureHeight = 0
|
||||||
|
private var mViewportWidth = 0
|
||||||
|
private var mViewportHeight = 0
|
||||||
|
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 1f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
|
||||||
|
vertexShaderCode)
|
||||||
|
val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
|
||||||
|
fragmentShaderCode)
|
||||||
|
mProgram = GLES20.glCreateProgram() // create empty OpenGL ES
|
||||||
|
// Program
|
||||||
|
GLES20.glAttachShader(mProgram, vertexShader) // add the vertex
|
||||||
|
// shader to program
|
||||||
|
GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment
|
||||||
|
// shader to
|
||||||
|
// program
|
||||||
|
GLES20.glLinkProgram(mProgram)
|
||||||
|
val positionHandle = GLES20.glGetAttribLocation(mProgram,
|
||||||
|
"aPosition")
|
||||||
|
val textureHandle = GLES20.glGetAttribLocation(mProgram,
|
||||||
|
"aTextureCoord")
|
||||||
|
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
|
||||||
|
GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4,
|
||||||
|
mVertexBuffer)
|
||||||
|
GLES20.glEnableVertexAttribArray(positionHandle)
|
||||||
|
GLES20.glVertexAttribPointer(textureHandle,
|
||||||
|
TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
|
||||||
|
TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer)
|
||||||
|
GLES20.glEnableVertexAttribArray(textureHandle)
|
||||||
|
GLES20.glUseProgram(mProgram)
|
||||||
|
var i = GLES20.glGetUniformLocation(mProgram, "Ytex")
|
||||||
|
GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */
|
||||||
|
i = GLES20.glGetUniformLocation(mProgram, "Utex")
|
||||||
|
GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */
|
||||||
|
i = GLES20.glGetUniformLocation(mProgram, "Vtex")
|
||||||
|
GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */
|
||||||
|
val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp")
|
||||||
|
val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt()
|
||||||
|
GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat())
|
||||||
|
mTextureWidth = 0
|
||||||
|
mTextureHeight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setupTextures(frame: Frame) {
|
||||||
|
if (mTextureIds[0] != 0) {
|
||||||
|
GLES20.glDeleteTextures(3, mTextureIds, 0)
|
||||||
|
}
|
||||||
|
GLES20.glGenTextures(3, mTextureIds, 0)
|
||||||
|
val w = frame.width
|
||||||
|
val h = frame.height
|
||||||
|
val hw = w + 1 shr 1
|
||||||
|
val hh = h + 1 shr 1
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h)
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh)
|
||||||
|
initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh)
|
||||||
|
mTextureWidth = frame.width
|
||||||
|
mTextureHeight = frame.height
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateTextures(frame: Frame) {
|
||||||
|
val width = frame.width
|
||||||
|
val height = frame.height
|
||||||
|
val half_width = width + 1 shr 1
|
||||||
|
val half_height = height + 1 shr 1
|
||||||
|
val y_size = width * height
|
||||||
|
val uv_size = half_width * half_height
|
||||||
|
val bb = frame.buffer
|
||||||
|
// If we are reusing this frame, make sure we reset position and
|
||||||
|
// limit
|
||||||
|
bb.clear()
|
||||||
|
if (bb.remaining() == y_size + uv_size * 2) {
|
||||||
|
bb.position(0)
|
||||||
|
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1)
|
||||||
|
GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width,
|
||||||
|
height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE,
|
||||||
|
bb)
|
||||||
|
bb.position(y_size)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE1)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||||
|
half_width, half_height, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, bb)
|
||||||
|
bb.position(y_size + uv_size)
|
||||||
|
GLES20.glActiveTexture(GLES20.GL_TEXTURE2)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2])
|
||||||
|
GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0,
|
||||||
|
half_width, half_height, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, bb)
|
||||||
|
} else {
|
||||||
|
mTextureWidth = 0
|
||||||
|
mTextureHeight = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
|
||||||
|
GLES20.glViewport(0, 0, width, height)
|
||||||
|
mViewportWidth = width
|
||||||
|
mViewportHeight = height
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadataListener: ThumbnailCircleVideoRendererMetadataListener? = null
|
||||||
|
override fun onDrawFrame(gl: GL10) {
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 0f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
mFrameLock.lock()
|
||||||
|
if (mCurrentFrame != null && !mVideoDisabled) {
|
||||||
|
GLES20.glUseProgram(mProgram)
|
||||||
|
if (mTextureWidth != mCurrentFrame!!.width
|
||||||
|
|| mTextureHeight != mCurrentFrame!!.height) {
|
||||||
|
setupTextures(mCurrentFrame!!)
|
||||||
|
}
|
||||||
|
updateTextures(mCurrentFrame!!)
|
||||||
|
Matrix.setIdentityM(mScaleMatrix, 0)
|
||||||
|
var scaleX = 1.0f
|
||||||
|
var scaleY = 1.0f
|
||||||
|
val ratio = (mCurrentFrame!!.width.toFloat()
|
||||||
|
/ mCurrentFrame!!.height)
|
||||||
|
val vratio = mViewportWidth.toFloat() / mViewportHeight
|
||||||
|
if (mVideoFitEnabled) {
|
||||||
|
if (ratio > vratio) {
|
||||||
|
scaleY = vratio / ratio
|
||||||
|
} else {
|
||||||
|
scaleX = ratio / vratio
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ratio < vratio) {
|
||||||
|
scaleY = vratio / ratio
|
||||||
|
} else {
|
||||||
|
scaleX = ratio / vratio
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Matrix.scaleM(mScaleMatrix, 0,
|
||||||
|
scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f,
|
||||||
|
scaleY, 1f)
|
||||||
|
metadataListener?.onMetadataReady(mCurrentFrame!!.metadata)
|
||||||
|
val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,
|
||||||
|
"uMVPMatrix")
|
||||||
|
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false,
|
||||||
|
mScaleMatrix, 0)
|
||||||
|
GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size,
|
||||||
|
GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer)
|
||||||
|
} else {
|
||||||
|
//black frame when video is disabled
|
||||||
|
gl.glClearColor(0f, 0f, 0f, 1f)
|
||||||
|
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun displayFrame(frame: Frame?) {
|
||||||
|
mFrameLock.lock()
|
||||||
|
if (mCurrentFrame != null) {
|
||||||
|
mCurrentFrame!!.recycle()
|
||||||
|
}
|
||||||
|
mCurrentFrame = frame
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disableVideo(b: Boolean) {
|
||||||
|
mFrameLock.lock()
|
||||||
|
mVideoDisabled = b
|
||||||
|
if (mVideoDisabled) {
|
||||||
|
if (mCurrentFrame != null) {
|
||||||
|
mCurrentFrame!!.recycle()
|
||||||
|
}
|
||||||
|
mCurrentFrame = null
|
||||||
|
}
|
||||||
|
mFrameLock.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableVideoFit(enableVideoFit: Boolean) {
|
||||||
|
mVideoFitEnabled = enableVideoFit
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// number of coordinates per vertex in this array
|
||||||
|
const val COORDS_PER_VERTEX = 3
|
||||||
|
const val TEXTURECOORDS_PER_VERTEX = 2
|
||||||
|
var mXYZCoords = floatArrayOf(
|
||||||
|
-1.0f, 1.0f, 0.0f, // top left
|
||||||
|
-1.0f, -1.0f, 0.0f, // bottom left
|
||||||
|
1.0f, -1.0f, 0.0f, // bottom right
|
||||||
|
1.0f, 1.0f, 0.0f // top right
|
||||||
|
)
|
||||||
|
var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f)
|
||||||
|
fun initializeTexture(name: Int, id: Int, width: Int, height: Int) {
|
||||||
|
GLES20.glActiveTexture(name)
|
||||||
|
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id)
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat())
|
||||||
|
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
|
||||||
|
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat())
|
||||||
|
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE,
|
||||||
|
width, height, 0, GLES20.GL_LUMINANCE,
|
||||||
|
GLES20.GL_UNSIGNED_BYTE, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadShader(type: Int, shaderCode: String?): Int {
|
||||||
|
val shader = GLES20.glCreateShader(type)
|
||||||
|
GLES20.glShaderSource(shader, shaderCode)
|
||||||
|
GLES20.glCompileShader(shader)
|
||||||
|
return shader
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4)
|
||||||
|
bb.order(ByteOrder.nativeOrder())
|
||||||
|
mVertexBuffer = bb.asFloatBuffer()
|
||||||
|
mVertexBuffer.put(mXYZCoords)
|
||||||
|
mVertexBuffer.position(0)
|
||||||
|
val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4)
|
||||||
|
tb.order(ByteOrder.nativeOrder())
|
||||||
|
mTextureBuffer = tb.asFloatBuffer()
|
||||||
|
mTextureBuffer.put(mUVCoords)
|
||||||
|
mTextureBuffer.position(0)
|
||||||
|
val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2)
|
||||||
|
dlb.order(ByteOrder.nativeOrder())
|
||||||
|
mDrawListBuffer = dlb.asShortBuffer()
|
||||||
|
mDrawListBuffer.put(mVertexIndex)
|
||||||
|
mDrawListBuffer.position(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFrame(frame: Frame) {
|
||||||
|
mRenderer.displayFrame(frame)
|
||||||
|
mView.requestRender()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setStyle(key: String, value: String) {
|
||||||
|
if (STYLE_VIDEO_SCALE == key) {
|
||||||
|
if (STYLE_VIDEO_FIT == value) {
|
||||||
|
mRenderer.enableVideoFit(true)
|
||||||
|
} else if (STYLE_VIDEO_FILL == value) {
|
||||||
|
mRenderer.enableVideoFit(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onVideoPropertiesChanged(videoEnabled: Boolean) {
|
||||||
|
mRenderer.disableVideo(!videoEnabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getView(): View {
|
||||||
|
return mView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
mView.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
mView.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val THUMBNAIL_SIZE = 90 //in dp
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
mView.setEGLContextClientVersion(2)
|
||||||
|
mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0)
|
||||||
|
mView.holder.setFormat(PixelFormat.TRANSLUCENT)
|
||||||
|
mRenderer = MyRenderer()
|
||||||
|
mView.setRenderer(mRenderer)
|
||||||
|
mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.hmg.hmgDr.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.DisplayMetrics
|
||||||
|
|
||||||
|
object ViewsUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @return the Screen height in DP
|
||||||
|
*/
|
||||||
|
fun getHeightDp(context: Context, isInDp: Boolean = false): Float {
|
||||||
|
val displayMetrics: DisplayMetrics = context.resources.displayMetrics
|
||||||
|
return if (isInDp) {
|
||||||
|
displayMetrics.heightPixels / displayMetrics.density
|
||||||
|
} else {
|
||||||
|
displayMetrics.heightPixels.toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context
|
||||||
|
* @return the screnn width in dp
|
||||||
|
*/
|
||||||
|
fun getWidthDp(context: Context, isInDp: Boolean = false): Float {
|
||||||
|
val displayMetrics: DisplayMetrics = context.resources.displayMetrics
|
||||||
|
return if (isInDp) {
|
||||||
|
displayMetrics.widthPixels / displayMetrics.density
|
||||||
|
} else {
|
||||||
|
displayMetrics.widthPixels.toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval">
|
||||||
|
|
||||||
|
<solid
|
||||||
|
android:color="@color/remoteBackground"/>
|
||||||
|
|
||||||
|
<stroke android:width="2dp" android:color="@color/text_color" />
|
||||||
|
|
||||||
|
<size
|
||||||
|
android:width="120dp"
|
||||||
|
android:height="120dp"/>
|
||||||
|
</shape>
|
||||||
|
After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,13H5v-2h14v2z"/>
|
||||||
|
</vector>
|
||||||
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="@color/text_color" />
|
||||||
|
<stroke
|
||||||
|
android:width="3dp"
|
||||||
|
android:color="@color/text_color" />
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<padding
|
||||||
|
android:bottom="0dp"
|
||||||
|
android:left="0dp"
|
||||||
|
android:right="0dp"
|
||||||
|
android:top="0dp" />
|
||||||
|
</shape>
|
||||||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<corners android:radius="1000dp"/>
|
||||||
|
|
||||||
|
<solid android:color="@color/green_dark"/>
|
||||||
|
|
||||||
|
</shape>
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.6 KiB |
@ -1,325 +0,0 @@
|
|||||||
PODS:
|
|
||||||
- Alamofire (4.9.1)
|
|
||||||
- barcode_scan (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- MTBBarcodeScanner
|
|
||||||
- SwiftProtobuf
|
|
||||||
- connectivity (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Reachability
|
|
||||||
- connectivity_for_web (0.1.0):
|
|
||||||
- Flutter
|
|
||||||
- connectivity_macos (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- device_info (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Firebase/CoreOnly (6.33.0):
|
|
||||||
- FirebaseCore (= 6.10.3)
|
|
||||||
- Firebase/Messaging (6.33.0):
|
|
||||||
- Firebase/CoreOnly
|
|
||||||
- FirebaseMessaging (~> 4.7.0)
|
|
||||||
- firebase_core (0.5.3):
|
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
|
||||||
- Flutter
|
|
||||||
- firebase_core_web (0.1.0):
|
|
||||||
- Flutter
|
|
||||||
- firebase_messaging (7.0.3):
|
|
||||||
- Firebase/CoreOnly (~> 6.33.0)
|
|
||||||
- Firebase/Messaging (~> 6.33.0)
|
|
||||||
- firebase_core
|
|
||||||
- Flutter
|
|
||||||
- FirebaseCore (6.10.3):
|
|
||||||
- FirebaseCoreDiagnostics (~> 1.6)
|
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
|
||||||
- GoogleUtilities/Logger (~> 6.7)
|
|
||||||
- FirebaseCoreDiagnostics (1.7.0):
|
|
||||||
- GoogleDataTransport (~> 7.4)
|
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
|
||||||
- GoogleUtilities/Logger (~> 6.7)
|
|
||||||
- nanopb (~> 1.30906.0)
|
|
||||||
- FirebaseInstallations (1.7.0):
|
|
||||||
- FirebaseCore (~> 6.10)
|
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
|
||||||
- PromisesObjC (~> 1.2)
|
|
||||||
- FirebaseInstanceID (4.8.0):
|
|
||||||
- FirebaseCore (~> 6.10)
|
|
||||||
- FirebaseInstallations (~> 1.6)
|
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
|
||||||
- FirebaseMessaging (4.7.1):
|
|
||||||
- FirebaseCore (~> 6.10)
|
|
||||||
- FirebaseInstanceID (~> 4.7)
|
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 6.7)
|
|
||||||
- GoogleUtilities/Environment (~> 6.7)
|
|
||||||
- GoogleUtilities/Reachability (~> 6.7)
|
|
||||||
- GoogleUtilities/UserDefaults (~> 6.7)
|
|
||||||
- Protobuf (>= 3.9.2, ~> 3.9)
|
|
||||||
- Flutter (1.0.0)
|
|
||||||
- flutter_flexible_toast (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_plugin_android_lifecycle (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- GoogleDataTransport (7.5.1):
|
|
||||||
- nanopb (~> 1.30906.0)
|
|
||||||
- GoogleUtilities/AppDelegateSwizzler (6.7.2):
|
|
||||||
- GoogleUtilities/Environment
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- GoogleUtilities/Network
|
|
||||||
- GoogleUtilities/Environment (6.7.2):
|
|
||||||
- PromisesObjC (~> 1.2)
|
|
||||||
- GoogleUtilities/Logger (6.7.2):
|
|
||||||
- GoogleUtilities/Environment
|
|
||||||
- GoogleUtilities/Network (6.7.2):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- "GoogleUtilities/NSData+zlib"
|
|
||||||
- GoogleUtilities/Reachability
|
|
||||||
- "GoogleUtilities/NSData+zlib (6.7.2)"
|
|
||||||
- GoogleUtilities/Reachability (6.7.2):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- GoogleUtilities/UserDefaults (6.7.2):
|
|
||||||
- GoogleUtilities/Logger
|
|
||||||
- hexcolor (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- imei_plugin (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- local_auth (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- maps_launcher (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- MTBBarcodeScanner (5.0.11)
|
|
||||||
- nanopb (1.30906.0):
|
|
||||||
- nanopb/decode (= 1.30906.0)
|
|
||||||
- nanopb/encode (= 1.30906.0)
|
|
||||||
- nanopb/decode (1.30906.0)
|
|
||||||
- nanopb/encode (1.30906.0)
|
|
||||||
- OpenTok (2.15.3)
|
|
||||||
- path_provider_linux (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- path_provider_windows (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- "permission_handler (5.1.0+2)":
|
|
||||||
- Flutter
|
|
||||||
- PromisesObjC (1.2.11)
|
|
||||||
- Protobuf (3.13.0)
|
|
||||||
- Reachability (3.2)
|
|
||||||
- screen (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_linux (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_macos (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_web (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- shared_preferences_windows (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- speech_to_text (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- Try
|
|
||||||
- SwiftProtobuf (1.9.0)
|
|
||||||
- Try (2.1.1)
|
|
||||||
- url_launcher (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- url_launcher_linux (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- url_launcher_macos (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- url_launcher_web (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- url_launcher_windows (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- video_player (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- video_player_web (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- wakelock (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- webview_flutter (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
|
||||||
- Alamofire
|
|
||||||
- barcode_scan (from `.symlinks/plugins/barcode_scan/ios`)
|
|
||||||
- connectivity (from `.symlinks/plugins/connectivity/ios`)
|
|
||||||
- connectivity_for_web (from `.symlinks/plugins/connectivity_for_web/ios`)
|
|
||||||
- connectivity_macos (from `.symlinks/plugins/connectivity_macos/ios`)
|
|
||||||
- device_info (from `.symlinks/plugins/device_info/ios`)
|
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
|
||||||
- firebase_core_web (from `.symlinks/plugins/firebase_core_web/ios`)
|
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
|
||||||
- Flutter (from `Flutter`)
|
|
||||||
- flutter_flexible_toast (from `.symlinks/plugins/flutter_flexible_toast/ios`)
|
|
||||||
- flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
|
|
||||||
- hexcolor (from `.symlinks/plugins/hexcolor/ios`)
|
|
||||||
- imei_plugin (from `.symlinks/plugins/imei_plugin/ios`)
|
|
||||||
- local_auth (from `.symlinks/plugins/local_auth/ios`)
|
|
||||||
- maps_launcher (from `.symlinks/plugins/maps_launcher/ios`)
|
|
||||||
- OpenTok
|
|
||||||
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`)
|
|
||||||
- path_provider_windows (from `.symlinks/plugins/path_provider_windows/ios`)
|
|
||||||
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
|
|
||||||
- screen (from `.symlinks/plugins/screen/ios`)
|
|
||||||
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
|
|
||||||
- shared_preferences_linux (from `.symlinks/plugins/shared_preferences_linux/ios`)
|
|
||||||
- shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
|
|
||||||
- shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`)
|
|
||||||
- shared_preferences_windows (from `.symlinks/plugins/shared_preferences_windows/ios`)
|
|
||||||
- speech_to_text (from `.symlinks/plugins/speech_to_text/ios`)
|
|
||||||
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
|
|
||||||
- url_launcher_linux (from `.symlinks/plugins/url_launcher_linux/ios`)
|
|
||||||
- url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`)
|
|
||||||
- url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`)
|
|
||||||
- url_launcher_windows (from `.symlinks/plugins/url_launcher_windows/ios`)
|
|
||||||
- video_player (from `.symlinks/plugins/video_player/ios`)
|
|
||||||
- video_player_web (from `.symlinks/plugins/video_player_web/ios`)
|
|
||||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
|
||||||
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
|
||||||
trunk:
|
|
||||||
- Alamofire
|
|
||||||
- Firebase
|
|
||||||
- FirebaseCore
|
|
||||||
- FirebaseCoreDiagnostics
|
|
||||||
- FirebaseInstallations
|
|
||||||
- FirebaseInstanceID
|
|
||||||
- FirebaseMessaging
|
|
||||||
- GoogleDataTransport
|
|
||||||
- GoogleUtilities
|
|
||||||
- MTBBarcodeScanner
|
|
||||||
- nanopb
|
|
||||||
- OpenTok
|
|
||||||
- PromisesObjC
|
|
||||||
- Protobuf
|
|
||||||
- Reachability
|
|
||||||
- SwiftProtobuf
|
|
||||||
- Try
|
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
|
||||||
barcode_scan:
|
|
||||||
:path: ".symlinks/plugins/barcode_scan/ios"
|
|
||||||
connectivity:
|
|
||||||
:path: ".symlinks/plugins/connectivity/ios"
|
|
||||||
connectivity_for_web:
|
|
||||||
:path: ".symlinks/plugins/connectivity_for_web/ios"
|
|
||||||
connectivity_macos:
|
|
||||||
:path: ".symlinks/plugins/connectivity_macos/ios"
|
|
||||||
device_info:
|
|
||||||
:path: ".symlinks/plugins/device_info/ios"
|
|
||||||
firebase_core:
|
|
||||||
:path: ".symlinks/plugins/firebase_core/ios"
|
|
||||||
firebase_core_web:
|
|
||||||
:path: ".symlinks/plugins/firebase_core_web/ios"
|
|
||||||
firebase_messaging:
|
|
||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
|
||||||
Flutter:
|
|
||||||
:path: Flutter
|
|
||||||
flutter_flexible_toast:
|
|
||||||
:path: ".symlinks/plugins/flutter_flexible_toast/ios"
|
|
||||||
flutter_plugin_android_lifecycle:
|
|
||||||
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
|
|
||||||
hexcolor:
|
|
||||||
:path: ".symlinks/plugins/hexcolor/ios"
|
|
||||||
imei_plugin:
|
|
||||||
:path: ".symlinks/plugins/imei_plugin/ios"
|
|
||||||
local_auth:
|
|
||||||
:path: ".symlinks/plugins/local_auth/ios"
|
|
||||||
maps_launcher:
|
|
||||||
:path: ".symlinks/plugins/maps_launcher/ios"
|
|
||||||
path_provider_linux:
|
|
||||||
:path: ".symlinks/plugins/path_provider_linux/ios"
|
|
||||||
path_provider_windows:
|
|
||||||
:path: ".symlinks/plugins/path_provider_windows/ios"
|
|
||||||
permission_handler:
|
|
||||||
:path: ".symlinks/plugins/permission_handler/ios"
|
|
||||||
screen:
|
|
||||||
:path: ".symlinks/plugins/screen/ios"
|
|
||||||
shared_preferences:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences/ios"
|
|
||||||
shared_preferences_linux:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_linux/ios"
|
|
||||||
shared_preferences_macos:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_macos/ios"
|
|
||||||
shared_preferences_web:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_web/ios"
|
|
||||||
shared_preferences_windows:
|
|
||||||
:path: ".symlinks/plugins/shared_preferences_windows/ios"
|
|
||||||
speech_to_text:
|
|
||||||
:path: ".symlinks/plugins/speech_to_text/ios"
|
|
||||||
url_launcher:
|
|
||||||
:path: ".symlinks/plugins/url_launcher/ios"
|
|
||||||
url_launcher_linux:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_linux/ios"
|
|
||||||
url_launcher_macos:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_macos/ios"
|
|
||||||
url_launcher_web:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_web/ios"
|
|
||||||
url_launcher_windows:
|
|
||||||
:path: ".symlinks/plugins/url_launcher_windows/ios"
|
|
||||||
video_player:
|
|
||||||
:path: ".symlinks/plugins/video_player/ios"
|
|
||||||
video_player_web:
|
|
||||||
:path: ".symlinks/plugins/video_player_web/ios"
|
|
||||||
wakelock:
|
|
||||||
:path: ".symlinks/plugins/wakelock/ios"
|
|
||||||
webview_flutter:
|
|
||||||
:path: ".symlinks/plugins/webview_flutter/ios"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
|
||||||
Alamofire: 85e8a02c69d6020a0d734f6054870d7ecb75cf18
|
|
||||||
barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479
|
|
||||||
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
|
|
||||||
connectivity_for_web: 2b8584556930d4bd490d82b836bcf45067ce345b
|
|
||||||
connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191
|
|
||||||
device_info: d7d233b645a32c40dfdc212de5cf646ca482f175
|
|
||||||
Firebase: 8db6f2d1b2c5e2984efba4949a145875a8f65fe5
|
|
||||||
firebase_core: 5d6a02f3d85acd5f8321c2d6d62877626a670659
|
|
||||||
firebase_core_web: d501d8b946b60c8af265428ce483b0fff5ad52d1
|
|
||||||
firebase_messaging: 0aea2cd5885b65e19ede58ee3507f485c992cc75
|
|
||||||
FirebaseCore: d889d9e12535b7f36ac8bfbf1713a0836a3012cd
|
|
||||||
FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1
|
|
||||||
FirebaseInstallations: 466c7b4d1f58fe16707693091da253726a731ed2
|
|
||||||
FirebaseInstanceID: bd3ffc24367f901a43c063b36c640b345a4a5dd1
|
|
||||||
FirebaseMessaging: 5eca4ef173de76253352511aafef774caa1cba2a
|
|
||||||
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
|
|
||||||
flutter_flexible_toast: 0547e740cae0c33bb7c51bcd931233f4584e1143
|
|
||||||
flutter_plugin_android_lifecycle: dc0b544e129eebb77a6bfb1239d4d1c673a60a35
|
|
||||||
GoogleDataTransport: f56af7caa4ed338dc8e138a5d7c5973e66440833
|
|
||||||
GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3
|
|
||||||
hexcolor: fdfb9c4258ad96e949c2dbcdf790a62194b8aa89
|
|
||||||
imei_plugin: cb1af7c223ac2d82dcd1457a7137d93d65d2a3cd
|
|
||||||
local_auth: 25938960984c3a7f6e3253e3f8d962fdd16852bd
|
|
||||||
maps_launcher: eae38ee13a9c3f210fa04e04bb4c073fa4c6ed92
|
|
||||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
|
||||||
nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc
|
|
||||||
OpenTok: fde03ecc5ea31fe0a453242847c4ee1f47e1d735
|
|
||||||
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
|
|
||||||
path_provider_windows: a2b81600c677ac1959367280991971cb9a1edb3b
|
|
||||||
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
|
|
||||||
PromisesObjC: 8c196f5a328c2cba3e74624585467a557dcb482f
|
|
||||||
Protobuf: 3dac39b34a08151c6d949560efe3f86134a3f748
|
|
||||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
|
||||||
screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0
|
|
||||||
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
|
|
||||||
shared_preferences_linux: afefbfe8d921e207f01ede8b60373d9e3b566b78
|
|
||||||
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
|
|
||||||
shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9
|
|
||||||
shared_preferences_windows: 36b76d6f54e76ead957e60b49e2f124b4cd3e6ae
|
|
||||||
speech_to_text: b43a7d99aef037bd758ed8e45d79bbac035d2dfe
|
|
||||||
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
|
|
||||||
Try: 5ef669ae832617b3cee58cb2c6f99fb767a4ff96
|
|
||||||
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
|
|
||||||
url_launcher_linux: ac237cb7a8058736e4aae38bdbcc748a4b394cc0
|
|
||||||
url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313
|
|
||||||
url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c
|
|
||||||
url_launcher_windows: 683d7c283894db8d1914d3ab2223b20cc1ad95d5
|
|
||||||
video_player: 9cc823b1d9da7e8427ee591e8438bfbcde500e6e
|
|
||||||
video_player_web: da8cadb8274ed4f8dbee8d7171b420dedd437ce7
|
|
||||||
wakelock: 0d4a70faf8950410735e3f61fb15d517c8a6efc4
|
|
||||||
webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: 649616dc336b3659ac6b2b25159d8e488e042b69
|
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "camera_back.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "camera_front.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.9 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "end_call.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 21 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "expand.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Group 8024.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "hide_video_icon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 906 B |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "mic_mute.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.4 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Group 8020.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.8 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "video_mute.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Group 8022.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.6 KiB |
@ -1,296 +1,366 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_7" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--Flutter View Controller-->
|
<!--Main App View Controller-->
|
||||||
<scene sceneID="tne-QT-ifu">
|
<scene sceneID="tne-QT-ifu">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
<viewController id="BYZ-38-t0r" customClass="MainAppViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</view>
|
</view>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="-45" y="1436"/>
|
<point key="canvasLocation" x="-1535" y="2239"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--View Controller-->
|
<!--Video Call View Controller-->
|
||||||
<scene sceneID="L7v-n1-KvF">
|
<scene sceneID="L7v-n1-KvF">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="t2c-G5-7AE" customClass="ViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
|
<viewController storyboardIdentifier="videoCall" id="t2c-G5-7AE" customClass="VideoCallViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<layoutGuides>
|
<layoutGuides>
|
||||||
<viewControllerLayoutGuide type="top" id="BIa-yr-ZMY"/>
|
<viewControllerLayoutGuide type="top" id="BIa-yr-ZMY"/>
|
||||||
<viewControllerLayoutGuide type="bottom" id="VIH-1T-Ife"/>
|
<viewControllerLayoutGuide type="bottom" id="VIH-1T-Ife"/>
|
||||||
</layoutGuides>
|
</layoutGuides>
|
||||||
<view key="view" contentMode="scaleToFill" id="PoR-7r-yNe">
|
<view key="view" contentMode="scaleToFill" id="PoR-7r-yNe">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6C5-o5-R1n" userLabel="controlButtonSpacer">
|
|
||||||
<rect key="frame" x="14" y="844" width="139" height="30"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="height" constant="30" id="0mU-Ko-Up3"/>
|
|
||||||
<constraint firstAttribute="width" constant="139" id="DNz-Ig-XOS"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yS9-HT-vp8" userLabel="controlButtonSpacer">
|
|
||||||
<rect key="frame" x="265" y="844" width="140" height="30"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="width" constant="140" id="Alm-7E-yeU"/>
|
|
||||||
<constraint firstAttribute="height" constant="30" id="amS-in-0UH"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
<view contentMode="scaleToFill" restorationIdentifier="VideoCallNavigationViewController" translatesAutoresizingMaskIntoConstraints="NO" id="eOT-Jr-GUl" userLabel="remoteVideo">
|
<view contentMode="scaleToFill" restorationIdentifier="VideoCallNavigationViewController" translatesAutoresizingMaskIntoConstraints="NO" id="eOT-Jr-GUl" userLabel="remoteVideo">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
<rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.98999999999999999" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</view>
|
</view>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="videoMutedIndicator" translatesAutoresizingMaskIntoConstraints="NO" id="CL1-2v-m1L" userLabel="remoteVideoMutedIndicator">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="videoMutedIndicator" translatesAutoresizingMaskIntoConstraints="NO" id="CL1-2v-m1L" userLabel="remoteVideoMutedIndicator">
|
||||||
<rect key="frame" x="147" y="398" width="120" height="100"/>
|
<rect key="frame" x="160.66666666666666" y="418.33333333333331" width="106.99999999999997" height="89.333333333333314"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="120" id="eon-3Z-74P"/>
|
<constraint firstAttribute="width" secondItem="CL1-2v-m1L" secondAttribute="height" multiplier="6:5" id="xqE-6Q-WAu"/>
|
||||||
<constraint firstAttribute="height" constant="100" id="iyK-hL-H3m"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0ZP-s2-kM5" userLabel="localVideo">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O5s-CJ-RFv">
|
||||||
<rect key="frame" x="270.5" y="138" width="103.5" height="224"/>
|
<rect key="frame" x="0.0" y="100" width="428" height="731"/>
|
||||||
|
<subviews>
|
||||||
|
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XHG-Db-3Px" customClass="AADraggableView" customModule="AADraggableView">
|
||||||
|
<rect key="frame" x="288" y="10" width="130" height="182"/>
|
||||||
|
<subviews>
|
||||||
|
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0ZP-s2-kM5" userLabel="localVideo">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="130" height="182"/>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||||
|
<integer key="value" value="5"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
<userDefinedRuntimeAttribute type="number" keyPath="layer.borderWidth">
|
||||||
|
<real key="value" value="0.5"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
</view>
|
</view>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="localVideoMutedBg" translatesAutoresizingMaskIntoConstraints="NO" id="A0G-cT-yji" userLabel="localVideoMutedBg">
|
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6y1-an-W7F">
|
||||||
<rect key="frame" x="215" y="138" width="159" height="224"/>
|
<rect key="frame" x="0.0" y="0.0" width="130" height="182"/>
|
||||||
</imageView>
|
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sK0-tB-H9u" userLabel="controlButtons">
|
|
||||||
<rect key="frame" x="0.0" y="740" width="414" height="80"/>
|
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NUO-2p-pzL" userLabel="videoMuteButton">
|
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="videoMutedIndicator" translatesAutoresizingMaskIntoConstraints="NO" id="FEH-bC-Hnh" userLabel="localVideoMutedIndicator">
|
||||||
<rect key="frame" x="29" y="20.5" width="39" height="39"/>
|
<rect key="frame" x="47" y="76" width="36" height="30"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="30" id="1iv-w5-GDT"/>
|
||||||
|
<constraint firstAttribute="width" constant="36" id="AwX-vQ-Ynn"/>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="39" id="CWU-fT-9gx"/>
|
<constraint firstItem="FEH-bC-Hnh" firstAttribute="centerX" secondItem="6y1-an-W7F" secondAttribute="centerX" id="dtO-VP-8qV"/>
|
||||||
<constraint firstAttribute="height" constant="39" id="nsM-Xv-O2N"/>
|
<constraint firstItem="FEH-bC-Hnh" firstAttribute="centerY" secondItem="6y1-an-W7F" secondAttribute="centerY" id="lpW-Vr-bH2"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" title="Button" image="speakerOff"/>
|
<userDefinedRuntimeAttributes>
|
||||||
<state key="selected" image="speakerOffSelected"/>
|
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||||
|
<integer key="value" value="5"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</view>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="0ZP-s2-kM5" firstAttribute="top" secondItem="XHG-Db-3Px" secondAttribute="top" id="E5A-Yq-Ods"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="6y1-an-W7F" secondAttribute="trailing" id="I0l-x2-rGO"/>
|
||||||
|
<constraint firstAttribute="width" secondItem="XHG-Db-3Px" secondAttribute="height" multiplier="1:1.4" id="M3V-vM-m0V"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="6y1-an-W7F" secondAttribute="bottom" id="T0D-IE-19P"/>
|
||||||
|
<constraint firstItem="6y1-an-W7F" firstAttribute="top" secondItem="XHG-Db-3Px" secondAttribute="top" id="T8b-Nd-jdR"/>
|
||||||
|
<constraint firstItem="6y1-an-W7F" firstAttribute="leading" secondItem="XHG-Db-3Px" secondAttribute="leading" id="brg-bp-MME"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="0ZP-s2-kM5" secondAttribute="bottom" id="hso-Od-7QF"/>
|
||||||
|
<constraint firstItem="0ZP-s2-kM5" firstAttribute="leading" secondItem="XHG-Db-3Px" secondAttribute="leading" id="k5R-AM-3J6"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="0ZP-s2-kM5" secondAttribute="trailing" id="z8V-qh-Rzq"/>
|
||||||
|
</constraints>
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="number" keyPath="padding">
|
||||||
|
<integer key="value" value="20"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
|
</view>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4S7-45-trL">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="428" height="731"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="didClickSpeakerButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="XHg-oo-TWD"/>
|
<action selector="btnSwipeVideoTapped:" destination="t2c-G5-7AE" eventType="touchUpInside" id="7AQ-6d-4iR"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N2h-FX-kF5" userLabel="muteButton">
|
</subviews>
|
||||||
<rect key="frame" x="98" y="20.5" width="39" height="39"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="39" id="Nv9-dR-SYL"/>
|
<constraint firstItem="4S7-45-trL" firstAttribute="leading" secondItem="O5s-CJ-RFv" secondAttribute="leading" id="AMe-9q-Xk9"/>
|
||||||
<constraint firstAttribute="height" constant="39" id="lFc-rS-c6B"/>
|
<constraint firstAttribute="trailing" secondItem="4S7-45-trL" secondAttribute="trailing" id="CX4-Rs-rep"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="XHG-Db-3Px" secondAttribute="trailing" constant="10" id="Ncy-sD-qeL"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="4S7-45-trL" secondAttribute="bottom" id="iJ9-pg-VXQ"/>
|
||||||
|
<constraint firstItem="XHG-Db-3Px" firstAttribute="top" secondItem="O5s-CJ-RFv" secondAttribute="top" constant="10" id="nM8-B7-soj"/>
|
||||||
|
<constraint firstItem="4S7-45-trL" firstAttribute="top" secondItem="O5s-CJ-RFv" secondAttribute="top" id="sNK-WK-tqV"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" title="Button" image="muteButton"/>
|
</view>
|
||||||
<state key="selected" image="muteButtonSelected"/>
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="WPH-QE-Fvp">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="didClickMuteButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="7lr-uj-db1"/>
|
<action selector="btnOnScreenTapped:" destination="t2c-G5-7AE" eventType="touchUpInside" id="jDS-QU-1VX"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ygd-al-G4F" userLabel="switchCameraButton">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sK0-tB-H9u" userLabel="controlButtons">
|
||||||
<rect key="frame" x="352" y="20.5" width="39" height="39"/>
|
<rect key="frame" x="0.0" y="831" width="428" height="95"/>
|
||||||
|
<subviews>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="r9w-8l-Zxj">
|
||||||
|
<rect key="frame" x="15" y="15" width="230" height="50"/>
|
||||||
|
<subviews>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="UZ6-EY-a59" userLabel="minMax">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="39" id="EHa-e5-BfD"/>
|
<constraint firstAttribute="width" secondItem="UZ6-EY-a59" secondAttribute="height" multiplier="1:1" id="Ula-Qc-wJE"/>
|
||||||
<constraint firstAttribute="height" constant="39" id="KEK-0n-HJw"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" title="Button" image="switchCameraButton"/>
|
<state key="normal" title="Button" image="float_video"/>
|
||||||
<state key="selected" image="switchCameraButtonSelected"/>
|
<state key="selected" image="expand_video"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="didClickSwitchCameraButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="TBa-Av-IXy"/>
|
<action selector="btnMinimizeTapped:" destination="t2c-G5-7AE" eventType="touchUpInside" id="xul-cC-cbm"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AoF-Up-Yu5" userLabel="hangUpButton">
|
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NUO-2p-pzL" userLabel="videoMuteButton">
|
||||||
<rect key="frame" x="174" y="4.5" width="71" height="71"/>
|
<rect key="frame" x="60" y="0.0" width="50" height="50"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="71" id="ACP-i0-gK8"/>
|
<constraint firstAttribute="width" secondItem="NUO-2p-pzL" secondAttribute="height" multiplier="1:1" id="KGm-Yp-MqK"/>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="71" id="DS1-a1-ep3"/>
|
|
||||||
<constraint firstAttribute="height" constant="71" id="ltx-rR-am0"/>
|
|
||||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="71" id="s7u-Zs-z2Q"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" image="hangUpButton"/>
|
<state key="normal" image="video_unmute"/>
|
||||||
|
<state key="selected" image="video_mute"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="hangUp:" destination="t2c-G5-7AE" eventType="touchUpInside" id="SUH-Gd-OXj"/>
|
<action selector="didClickVideoMuteButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="nk9-nS-UDE"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="7vf-kV-eQ5" userLabel="videoMuteButton">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N2h-FX-kF5" userLabel="muteButton">
|
||||||
<rect key="frame" x="283" y="20.5" width="39" height="39"/>
|
<rect key="frame" x="120" y="0.0" width="50" height="50"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="39" id="7Rd-r8-zJP"/>
|
<constraint firstAttribute="width" secondItem="N2h-FX-kF5" secondAttribute="height" multiplier="1:1" id="hI1-G0-K3C"/>
|
||||||
<constraint firstAttribute="width" constant="39" id="mwK-hd-jIy"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
<state key="normal" title="Button" image="videoMuteButton"/>
|
<state key="normal" image="mic_unmute"/>
|
||||||
<state key="selected" image="videoMuteButtonSelected"/>
|
<state key="selected" image="mic_mute"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="didClickVideoMuteButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="Hza-Ft-NNB"/>
|
<action selector="didClickMuteButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="7lr-uj-db1"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9g2-IH-l8e" userLabel="controlButtonSpacer">
|
<button opaque="NO" contentMode="scaleToFill" selected="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="lar-xK-rhR" userLabel="switchCamera">
|
||||||
<rect key="frame" x="396" y="0.0" width="18" height="80"/>
|
<rect key="frame" x="180" y="0.0" width="50" height="50"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="7f6-zT-RoW"/>
|
<constraint firstAttribute="width" secondItem="lar-xK-rhR" secondAttribute="height" multiplier="1:1" id="Wpc-dx-kpF"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="cmy-aX-hM0"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
<state key="normal" image="camera_back"/>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a4N-1U-1Yt" userLabel="controlButtonSpacer">
|
<state key="selected" image="camera_front"/>
|
||||||
<rect key="frame" x="328" y="0.0" width="18" height="80"/>
|
<connections>
|
||||||
|
<action selector="didClickSwitchCameraButton:" destination="t2c-G5-7AE" eventType="touchUpInside" id="S3g-7j-Ca0"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="X8j-wu-KrQ"/>
|
<constraint firstAttribute="height" constant="50" id="3L0-3h-Bxg"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="vkd-63-bmN"/>
|
<constraint firstItem="lar-xK-rhR" firstAttribute="width" secondItem="lar-xK-rhR" secondAttribute="height" multiplier="1:1" id="R46-j0-zPf"/>
|
||||||
|
<constraint firstItem="UZ6-EY-a59" firstAttribute="height" secondItem="NUO-2p-pzL" secondAttribute="height" id="kK6-uF-bf6"/>
|
||||||
|
<constraint firstItem="N2h-FX-kF5" firstAttribute="height" secondItem="NUO-2p-pzL" secondAttribute="height" id="o4R-49-iMe"/>
|
||||||
|
<constraint firstAttribute="height" constant="30" id="y90-hA-p5Z"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
<variation key="default">
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GbA-j6-191" userLabel="controlButtonSpacer">
|
<mask key="constraints">
|
||||||
<rect key="frame" x="259" y="0.0" width="18" height="80"/>
|
<exclude reference="y90-hA-p5Z"/>
|
||||||
|
</mask>
|
||||||
|
</variation>
|
||||||
|
</stackView>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AoF-Up-Yu5" userLabel="hangUpButton">
|
||||||
|
<rect key="frame" x="363" y="15" width="50" height="50"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="Bz0-tD-Q4d"/>
|
<constraint firstAttribute="width" secondItem="AoF-Up-Yu5" secondAttribute="height" multiplier="1:1" id="6LJ-QR-WEY"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="Ovg-ap-S7E"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
<state key="normal" image="end_call"/>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="h0g-z5-Y95" userLabel="controlButtonSpacer">
|
<connections>
|
||||||
<rect key="frame" x="143" y="0.0" width="18" height="80"/>
|
<action selector="hangUp:" destination="t2c-G5-7AE" eventType="touchUpInside" id="SUH-Gd-OXj"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="0.18431372549019609" green="0.1764705882352941" blue="0.16470588235294117" alpha="0.5" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="80" id="Vaj-Va-jZn"/>
|
<constraint firstItem="r9w-8l-Zxj" firstAttribute="top" secondItem="sK0-tB-H9u" secondAttribute="top" constant="15" id="00C-1i-sGc"/>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="Wv5-ys-Ho4"/>
|
<constraint firstItem="AoF-Up-Yu5" firstAttribute="bottom" secondItem="r9w-8l-Zxj" secondAttribute="bottom" id="1kB-OK-b0L"/>
|
||||||
|
<constraint firstItem="r9w-8l-Zxj" firstAttribute="leading" secondItem="sK0-tB-H9u" secondAttribute="leading" priority="900" constant="5" id="6B7-94-Myo"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="AoF-Up-Yu5" secondAttribute="trailing" priority="900" constant="5" id="DgE-WQ-KQm"/>
|
||||||
|
<constraint firstItem="r9w-8l-Zxj" firstAttribute="top" secondItem="sK0-tB-H9u" secondAttribute="top" priority="900" constant="5" id="Ft5-cy-2d0"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="r9w-8l-Zxj" secondAttribute="bottom" constant="30" id="G9u-kw-mVz"/>
|
||||||
|
<constraint firstItem="AoF-Up-Yu5" firstAttribute="top" secondItem="r9w-8l-Zxj" secondAttribute="top" id="H4s-Y8-HAI"/>
|
||||||
|
<constraint firstAttribute="trailing" secondItem="AoF-Up-Yu5" secondAttribute="trailing" constant="15" id="flB-AR-zo3"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="r9w-8l-Zxj" secondAttribute="bottom" priority="900" constant="5" id="n0r-vM-wKh"/>
|
||||||
|
<constraint firstItem="r9w-8l-Zxj" firstAttribute="leading" secondItem="sK0-tB-H9u" secondAttribute="leading" constant="15" id="x13-gZ-cYp"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gop-Yl-2fm" userLabel="controlButtonSpacer">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2nj-Va-L7c" userLabel="TopBar">
|
||||||
<rect key="frame" x="73" y="0.0" width="18" height="80"/>
|
<rect key="frame" x="0.0" y="0.0" width="428" height="100"/>
|
||||||
|
<subviews>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="n8H-om-4LV">
|
||||||
|
<rect key="frame" x="398" y="75" width="25" height="25"/>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="iqX-Wz-fb1"/>
|
<constraint firstAttribute="height" constant="25" id="dyc-7x-bTk"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="j0P-xC-zSP"/>
|
<constraint firstAttribute="width" constant="25" id="tYx-Ul-0Pf"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||||
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JCG-W9-5ko" userLabel="controlButtonSpacer">
|
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<rect key="frame" x="6" y="0.0" width="18" height="80"/>
|
<state key="normal" title="●">
|
||||||
|
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
</state>
|
||||||
|
<connections>
|
||||||
|
<action selector="circleFloatBtnTapped:" destination="t2c-G5-7AE" eventType="touchUpInside" id="2mC-ry-Lis"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="bvC-Fa-s3m">
|
||||||
|
<rect key="frame" x="15" y="50" width="398" height="30"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Al-Anoud Al-Anoud" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Zct-62-YE6">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="328" height="30"/>
|
||||||
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="25"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8Xn-w6-Mox">
|
||||||
|
<rect key="frame" x="338" y="3" width="60" height="24"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="-- : --" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Btq-Ll-BPH">
|
||||||
|
<rect key="frame" x="13.333333333333314" y="5.0000000000000009" width="33.666666666666664" height="14.333333333333336"/>
|
||||||
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="12"/>
|
||||||
|
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="0.0018553551427920477" green="0.59902576721627221" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" priority="750" constant="18" id="La6-ZY-Qs8"/>
|
<constraint firstAttribute="width" constant="60" id="InL-xK-60G"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="mf9-Qg-gVZ"/>
|
<constraint firstItem="Btq-Ll-BPH" firstAttribute="centerY" secondItem="8Xn-w6-Mox" secondAttribute="centerY" id="Vbi-zv-vUQ"/>
|
||||||
|
<constraint firstItem="Btq-Ll-BPH" firstAttribute="centerX" secondItem="8Xn-w6-Mox" secondAttribute="centerX" id="WNT-XA-AW6"/>
|
||||||
|
<constraint firstAttribute="height" constant="24" id="Zck-PD-EN0"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
<userDefinedRuntimeAttributes>
|
||||||
|
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||||
|
<integer key="value" value="12"/>
|
||||||
|
</userDefinedRuntimeAttribute>
|
||||||
|
</userDefinedRuntimeAttributes>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
</stackView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="0.18431372549019609" green="0.1764705882352941" blue="0.16470588235294117" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="displayP3"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="9g2-IH-l8e" firstAttribute="leading" secondItem="ygd-al-G4F" secondAttribute="trailing" constant="5" id="0Bv-9b-HQh"/>
|
<constraint firstAttribute="height" constant="100" id="6eP-Zl-97q"/>
|
||||||
<constraint firstItem="a4N-1U-1Yt" firstAttribute="leading" secondItem="7vf-kV-eQ5" secondAttribute="trailing" constant="6" id="4vp-mw-gRE"/>
|
<constraint firstAttribute="trailing" secondItem="n8H-om-4LV" secondAttribute="trailing" constant="5" id="7Uq-4Q-ywD"/>
|
||||||
<constraint firstAttribute="height" constant="80" id="5QG-54-ulG"/>
|
<constraint firstAttribute="bottom" secondItem="bvC-Fa-s3m" secondAttribute="bottom" priority="900" constant="5" id="HgY-Dw-B9R"/>
|
||||||
<constraint firstItem="GbA-j6-191" firstAttribute="width" secondItem="h0g-z5-Y95" secondAttribute="width" id="5cw-b2-SPx"/>
|
<constraint firstAttribute="bottom" secondItem="n8H-om-4LV" secondAttribute="bottom" id="Nr2-zL-avJ"/>
|
||||||
<constraint firstItem="h0g-z5-Y95" firstAttribute="width" secondItem="gop-Yl-2fm" secondAttribute="width" id="7oE-3V-2Gc"/>
|
<constraint firstAttribute="bottom" secondItem="bvC-Fa-s3m" secondAttribute="bottom" constant="20" id="PWn-Sb-O8B"/>
|
||||||
<constraint firstItem="7vf-kV-eQ5" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="8zH-6k-6Wz"/>
|
<constraint firstItem="bvC-Fa-s3m" firstAttribute="leading" secondItem="2nj-Va-L7c" secondAttribute="leading" constant="15" id="YH4-fV-fkQ"/>
|
||||||
<constraint firstItem="gop-Yl-2fm" firstAttribute="leading" secondItem="NUO-2p-pzL" secondAttribute="trailing" constant="5" id="Bbh-OY-I9f"/>
|
<constraint firstAttribute="trailing" secondItem="bvC-Fa-s3m" secondAttribute="trailing" constant="15" id="oq6-Oi-i7g"/>
|
||||||
<constraint firstItem="NUO-2p-pzL" firstAttribute="leading" secondItem="JCG-W9-5ko" secondAttribute="trailing" constant="5" id="Ccz-Qq-RXf"/>
|
<constraint firstAttribute="height" priority="900" constant="25" id="s8H-wK-WPB"/>
|
||||||
<constraint firstItem="gop-Yl-2fm" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="DE6-nZ-rEI"/>
|
|
||||||
<constraint firstItem="GbA-j6-191" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="EVH-xy-wpT"/>
|
|
||||||
<constraint firstItem="ygd-al-G4F" firstAttribute="leading" secondItem="a4N-1U-1Yt" secondAttribute="trailing" constant="6" id="FNy-Br-FIj"/>
|
|
||||||
<constraint firstItem="NUO-2p-pzL" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="Fme-oB-F7i"/>
|
|
||||||
<constraint firstItem="GbA-j6-191" firstAttribute="leading" secondItem="AoF-Up-Yu5" secondAttribute="trailing" constant="14" id="GxO-Fe-iqR"/>
|
|
||||||
<constraint firstItem="JCG-W9-5ko" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="HPP-q4-IDT"/>
|
|
||||||
<constraint firstItem="h0g-z5-Y95" firstAttribute="leading" secondItem="N2h-FX-kF5" secondAttribute="trailing" constant="6" id="I2J-pE-7yx"/>
|
|
||||||
<constraint firstItem="7vf-kV-eQ5" firstAttribute="leading" secondItem="GbA-j6-191" secondAttribute="trailing" constant="6" id="MVo-If-UVQ"/>
|
|
||||||
<constraint firstItem="a4N-1U-1Yt" firstAttribute="width" secondItem="GbA-j6-191" secondAttribute="width" id="Me9-IC-YE2"/>
|
|
||||||
<constraint firstItem="N2h-FX-kF5" firstAttribute="leading" secondItem="gop-Yl-2fm" secondAttribute="trailing" constant="7" id="RHr-s8-sAg"/>
|
|
||||||
<constraint firstItem="h0g-z5-Y95" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="RJj-Uh-H2E"/>
|
|
||||||
<constraint firstItem="a4N-1U-1Yt" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="Tb2-6o-Wqh"/>
|
|
||||||
<constraint firstItem="AoF-Up-Yu5" firstAttribute="leading" secondItem="h0g-z5-Y95" secondAttribute="trailing" constant="13" id="VZS-xZ-nbe"/>
|
|
||||||
<constraint firstItem="NUO-2p-pzL" firstAttribute="leading" secondItem="JCG-W9-5ko" secondAttribute="trailing" constant="5" id="Z1j-5z-34E"/>
|
|
||||||
<constraint firstItem="7vf-kV-eQ5" firstAttribute="leading" secondItem="GbA-j6-191" secondAttribute="trailing" constant="6" id="ZjD-GK-SkY"/>
|
|
||||||
<constraint firstItem="ygd-al-G4F" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="bJA-GM-b2E"/>
|
|
||||||
<constraint firstItem="ygd-al-G4F" firstAttribute="leading" secondItem="a4N-1U-1Yt" secondAttribute="trailing" constant="6" id="eFd-3F-A5f"/>
|
|
||||||
<constraint firstItem="JCG-W9-5ko" firstAttribute="leading" secondItem="sK0-tB-H9u" secondAttribute="leading" constant="6" id="f0s-gb-347"/>
|
|
||||||
<constraint firstItem="gop-Yl-2fm" firstAttribute="leading" secondItem="NUO-2p-pzL" secondAttribute="trailing" constant="5" id="frf-I5-Rs9"/>
|
|
||||||
<constraint firstItem="gop-Yl-2fm" firstAttribute="width" secondItem="JCG-W9-5ko" secondAttribute="width" id="i84-jd-Hwr"/>
|
|
||||||
<constraint firstItem="N2h-FX-kF5" firstAttribute="leading" secondItem="gop-Yl-2fm" secondAttribute="trailing" constant="7" id="jlv-lR-Nlf"/>
|
|
||||||
<constraint firstItem="N2h-FX-kF5" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="nU8-Hw-s0U"/>
|
|
||||||
<constraint firstItem="9g2-IH-l8e" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="pxq-U1-zP5"/>
|
|
||||||
<constraint firstItem="AoF-Up-Yu5" firstAttribute="centerY" secondItem="sK0-tB-H9u" secondAttribute="centerY" id="ql2-fm-OeZ"/>
|
|
||||||
<constraint firstItem="9g2-IH-l8e" firstAttribute="width" secondItem="a4N-1U-1Yt" secondAttribute="width" id="uXs-zM-gyf"/>
|
|
||||||
<constraint firstItem="h0g-z5-Y95" firstAttribute="leading" secondItem="N2h-FX-kF5" secondAttribute="trailing" constant="6" id="uia-9X-UrW"/>
|
|
||||||
<constraint firstItem="a4N-1U-1Yt" firstAttribute="leading" secondItem="7vf-kV-eQ5" secondAttribute="trailing" constant="6" id="vgH-Oj-HJc"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="9g2-IH-l8e" secondAttribute="trailing" id="vng-6I-eYj"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="videoMutedIndicator" translatesAutoresizingMaskIntoConstraints="NO" id="FEH-bC-Hnh" userLabel="localVideoMutedIndicator">
|
|
||||||
<rect key="frame" x="276" y="235" width="36" height="30"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="height" constant="30" id="1iv-w5-GDT"/>
|
|
||||||
<constraint firstAttribute="width" constant="36" id="AwX-vQ-Ynn"/>
|
|
||||||
</constraints>
|
|
||||||
</imageView>
|
|
||||||
</subviews>
|
</subviews>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="VIH-1T-Ife" firstAttribute="top" secondItem="sK0-tB-H9u" secondAttribute="bottom" constant="42" id="1tT-KH-NEk"/>
|
<constraint firstItem="eOT-Jr-GUl" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="4xz-lj-CXd"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="sK0-tB-H9u" secondAttribute="trailing" id="6K9-n9-ceJ"/>
|
<constraint firstAttribute="bottom" secondItem="eOT-Jr-GUl" secondAttribute="bottom" id="5Ae-F1-hSz"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="6C5-o5-R1n" secondAttribute="bottom" constant="22" id="76x-6M-xOb"/>
|
<constraint firstItem="WPH-QE-Fvp" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="5Yr-p4-csA"/>
|
||||||
<constraint firstItem="yS9-HT-vp8" firstAttribute="top" secondItem="sK0-tB-H9u" secondAttribute="bottom" constant="24" id="9zS-Fw-oaT"/>
|
<constraint firstItem="2nj-Va-L7c" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="8Gx-Tb-bpo"/>
|
||||||
<constraint firstItem="eOT-Jr-GUl" firstAttribute="centerX" secondItem="PoR-7r-yNe" secondAttribute="centerX" id="HMH-Hc-ofZ"/>
|
<constraint firstItem="O5s-CJ-RFv" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="Hyn-9r-k8s"/>
|
||||||
<constraint firstItem="FEH-bC-Hnh" firstAttribute="centerY" secondItem="0ZP-s2-kM5" secondAttribute="centerY" id="K8x-bd-bS9"/>
|
<constraint firstItem="sK0-tB-H9u" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="Itp-Pe-kh9"/>
|
||||||
<constraint firstItem="eOT-Jr-GUl" firstAttribute="width" secondItem="PoR-7r-yNe" secondAttribute="width" id="PH6-qw-V6p"/>
|
<constraint firstItem="2nj-Va-L7c" firstAttribute="top" secondItem="PoR-7r-yNe" secondAttribute="top" id="LDC-Rq-79f"/>
|
||||||
<constraint firstItem="eOT-Jr-GUl" firstAttribute="centerY" secondItem="PoR-7r-yNe" secondAttribute="centerY" id="Prz-4m-LHB"/>
|
<constraint firstItem="XHG-Db-3Px" firstAttribute="height" secondItem="eOT-Jr-GUl" secondAttribute="height" multiplier="0.196544" id="LwG-7m-Ihd"/>
|
||||||
<constraint firstItem="0ZP-s2-kM5" firstAttribute="width" secondItem="PoR-7r-yNe" secondAttribute="width" multiplier="0.25" id="QCm-L0-oF7"/>
|
<constraint firstAttribute="trailing" secondItem="eOT-Jr-GUl" secondAttribute="trailing" id="Pcn-K9-H92"/>
|
||||||
<constraint firstItem="sK0-tB-H9u" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" id="TPj-1d-lx6"/>
|
<constraint firstAttribute="bottom" secondItem="sK0-tB-H9u" secondAttribute="bottom" id="Tu5-Op-mnF"/>
|
||||||
<constraint firstItem="CL1-2v-m1L" firstAttribute="centerY" secondItem="PoR-7r-yNe" secondAttribute="centerY" id="UGv-46-ri8"/>
|
<constraint firstItem="CL1-2v-m1L" firstAttribute="centerY" secondItem="PoR-7r-yNe" secondAttribute="centerY" id="UGv-46-ri8"/>
|
||||||
<constraint firstAttribute="trailingMargin" secondItem="0ZP-s2-kM5" secondAttribute="trailing" constant="20" id="UZX-Yj-Efk"/>
|
<constraint firstAttribute="trailing" secondItem="O5s-CJ-RFv" secondAttribute="trailing" id="VcP-8e-3Un"/>
|
||||||
<constraint firstItem="A0G-cT-yji" firstAttribute="width" secondItem="0ZP-s2-kM5" secondAttribute="width" constant="55.5" id="WMH-vd-rQe"/>
|
|
||||||
<constraint firstItem="CL1-2v-m1L" firstAttribute="centerX" secondItem="PoR-7r-yNe" secondAttribute="centerX" id="Xt8-k3-fDj"/>
|
<constraint firstItem="CL1-2v-m1L" firstAttribute="centerX" secondItem="PoR-7r-yNe" secondAttribute="centerX" id="Xt8-k3-fDj"/>
|
||||||
<constraint firstItem="FEH-bC-Hnh" firstAttribute="centerX" secondItem="0ZP-s2-kM5" secondAttribute="centerX" constant="-28.25" id="Yvq-7p-bjS"/>
|
<constraint firstItem="CL1-2v-m1L" firstAttribute="width" secondItem="PoR-7r-yNe" secondAttribute="width" multiplier="0.25" id="Yce-bz-JBd"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="yS9-HT-vp8" secondAttribute="bottom" constant="22" id="bVF-wg-lH8"/>
|
<constraint firstItem="WPH-QE-Fvp" firstAttribute="top" secondItem="PoR-7r-yNe" secondAttribute="top" id="ddA-LD-2O3"/>
|
||||||
<constraint firstItem="6C5-o5-R1n" firstAttribute="leading" secondItem="PoR-7r-yNe" secondAttribute="leading" constant="14" id="der-54-SZ4"/>
|
<constraint firstItem="sK0-tB-H9u" firstAttribute="top" secondItem="O5s-CJ-RFv" secondAttribute="bottom" id="eOi-4p-iMm"/>
|
||||||
<constraint firstItem="A0G-cT-yji" firstAttribute="centerX" secondItem="0ZP-s2-kM5" secondAttribute="centerX" constant="-27.75" id="ga5-7D-8CU"/>
|
<constraint firstAttribute="trailing" secondItem="WPH-QE-Fvp" secondAttribute="trailing" id="evw-Oc-GgJ"/>
|
||||||
<constraint firstItem="A0G-cT-yji" firstAttribute="height" secondItem="0ZP-s2-kM5" secondAttribute="height" id="hMV-RD-NwE"/>
|
<constraint firstItem="O5s-CJ-RFv" firstAttribute="top" secondItem="2nj-Va-L7c" secondAttribute="bottom" id="fLH-dK-xpa"/>
|
||||||
<constraint firstItem="A0G-cT-yji" firstAttribute="centerY" secondItem="0ZP-s2-kM5" secondAttribute="centerY" id="nBC-L0-5Pe"/>
|
<constraint firstItem="eOT-Jr-GUl" firstAttribute="top" secondItem="PoR-7r-yNe" secondAttribute="top" id="gFm-X8-RIU"/>
|
||||||
<constraint firstItem="0ZP-s2-kM5" firstAttribute="height" secondItem="PoR-7r-yNe" secondAttribute="height" multiplier="0.25" id="pq3-Iv-N4l"/>
|
<constraint firstAttribute="trailing" secondItem="sK0-tB-H9u" secondAttribute="trailing" id="gSh-7K-3p5"/>
|
||||||
<constraint firstItem="0ZP-s2-kM5" firstAttribute="top" secondItem="BIa-yr-ZMY" secondAttribute="bottom" constant="50" id="qrs-H2-Rw4"/>
|
<constraint firstAttribute="bottom" secondItem="WPH-QE-Fvp" secondAttribute="bottom" id="sYs-wp-cot"/>
|
||||||
<constraint firstItem="eOT-Jr-GUl" firstAttribute="height" secondItem="PoR-7r-yNe" secondAttribute="height" id="rbk-Lc-qip"/>
|
<constraint firstAttribute="trailing" secondItem="2nj-Va-L7c" secondAttribute="trailing" id="vQp-Bv-IVU"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="yS9-HT-vp8" secondAttribute="trailing" constant="9" id="vEv-GY-lDH"/>
|
|
||||||
<constraint firstItem="6C5-o5-R1n" firstAttribute="top" secondItem="sK0-tB-H9u" secondAttribute="bottom" constant="24" id="xhd-lu-lFH"/>
|
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" id="s5b-6P-Hwj"/>
|
<navigationItem key="navigationItem" id="s5b-6P-Hwj"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
<outlet property="btnMinimize" destination="UZ6-EY-a59" id="bDC-LS-qlX"/>
|
||||||
|
<outlet property="btnScreenTap" destination="WPH-QE-Fvp" id="wiN-5a-WJO"/>
|
||||||
|
<outlet property="camSwitchBtn" destination="lar-xK-rhR" id="tde-s5-Mji"/>
|
||||||
<outlet property="controlButtons" destination="sK0-tB-H9u" id="mDK-cq-oQz"/>
|
<outlet property="controlButtons" destination="sK0-tB-H9u" id="mDK-cq-oQz"/>
|
||||||
<outlet property="localVideo" destination="0ZP-s2-kM5" id="C68-k7-h5j"/>
|
<outlet property="fullVideoView" destination="eOT-Jr-GUl" id="VKE-el-YGR"/>
|
||||||
<outlet property="localVideoMutedBg" destination="A0G-cT-yji" id="5Ia-9g-7CT"/>
|
<outlet property="hideVideoBtn" destination="n8H-om-4LV" id="tTp-Ep-XKS"/>
|
||||||
<outlet property="localVideoMutedIndicator" destination="FEH-bC-Hnh" id="PKd-gQ-Jct"/>
|
<outlet property="lblCallDuration" destination="Btq-Ll-BPH" id="Jdh-yK-PEx"/>
|
||||||
<outlet property="remoteVideo" destination="eOT-Jr-GUl" id="VKE-el-YGR"/>
|
<outlet property="lblRemoteUsername" destination="Zct-62-YE6" id="OQ0-mf-mvc"/>
|
||||||
|
<outlet property="localVideoContainer" destination="O5s-CJ-RFv" id="bh9-Yr-UGv"/>
|
||||||
|
<outlet property="localVideoMutedBg" destination="6y1-an-W7F" id="5FF-Ak-Vxb"/>
|
||||||
|
<outlet property="micMuteBtn" destination="N2h-FX-kF5" id="zgK-g1-Ndr"/>
|
||||||
<outlet property="remoteVideoMutedIndicator" destination="CL1-2v-m1L" id="aJ0-QC-m9Y"/>
|
<outlet property="remoteVideoMutedIndicator" destination="CL1-2v-m1L" id="aJ0-QC-m9Y"/>
|
||||||
|
<outlet property="smallVideoView" destination="0ZP-s2-kM5" id="C68-k7-h5j"/>
|
||||||
|
<outlet property="topBar" destination="2nj-Va-L7c" id="Zt4-J2-uw8"/>
|
||||||
|
<outlet property="videoMuteBtn" destination="NUO-2p-pzL" id="XCc-nu-N8P"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="s8H-wK-WPB" collectionClass="NSMutableArray" id="XTM-jR-Cos"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="HgY-Dw-B9R" collectionClass="NSMutableArray" id="Fi8-YX-9iQ"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="Ft5-cy-2d0" collectionClass="NSMutableArray" id="Ze3-H8-gj4"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="n0r-vM-wKh" collectionClass="NSMutableArray" id="IaQ-TS-ng8"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="G9u-kw-mVz" collectionClass="NSMutableArray" id="TaK-5m-byK"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="00C-1i-sGc" collectionClass="NSMutableArray" id="vmx-rp-JZI"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="PWn-Sb-O8B" collectionClass="NSMutableArray" id="pK4-yA-36p"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="6eP-Zl-97q" collectionClass="NSMutableArray" id="dxk-ol-uAW"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="3L0-3h-Bxg" collectionClass="NSMutableArray" id="w3Q-AR-TQY"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="y90-hA-p5Z" collectionClass="NSMutableArray" id="INL-Bc-eTM"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="DgE-WQ-KQm" collectionClass="NSMutableArray" id="zy0-aI-bnY"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="flB-AR-zo3" collectionClass="NSMutableArray" id="hwu-U4-5s5"/>
|
||||||
|
<outletCollection property="minimizeConstraint" destination="6B7-94-Myo" collectionClass="NSMutableArray" id="epM-Kg-2yi"/>
|
||||||
|
<outletCollection property="maximisedConstraint" destination="x13-gZ-cYp" collectionClass="NSMutableArray" id="uLI-UQ-yIo"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="x33-EE-6Ak" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="x33-EE-6Ak" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="1685.5072463768117" y="1435.7142857142856"/>
|
<point key="canvasLocation" x="-797.66355140186909" y="2238.6609071274302"/>
|
||||||
</scene>
|
|
||||||
<!--Navigation Controller-->
|
|
||||||
<scene sceneID="GvA-TT-FAo">
|
|
||||||
<objects>
|
|
||||||
<navigationController restorationIdentifier="ViewControllerNav" storyboardIdentifier="ViewControllerNav" id="0WJ-RG-MEh" sceneMemberID="viewController">
|
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="S7n-df-cyC">
|
|
||||||
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
</navigationBar>
|
|
||||||
<connections>
|
|
||||||
<segue destination="t2c-G5-7AE" kind="relationship" relationship="rootViewController" id="L74-If-nYJ"/>
|
|
||||||
</connections>
|
|
||||||
</navigationController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="vSx-dK-kQe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="880" y="1436"/>
|
|
||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="hangUpButton" width="71" height="71"/>
|
<image name="camera_back" width="198" height="202"/>
|
||||||
<image name="localVideoMutedBg" width="90" height="120"/>
|
<image name="camera_front" width="198" height="202"/>
|
||||||
<image name="muteButton" width="39" height="39"/>
|
<image name="end_call" width="488" height="488"/>
|
||||||
<image name="muteButtonSelected" width="39" height="39"/>
|
<image name="expand_video" width="202" height="199"/>
|
||||||
<image name="speakerOff" width="39" height="39"/>
|
<image name="float_video" width="202" height="202"/>
|
||||||
<image name="speakerOffSelected" width="39" height="39"/>
|
<image name="mic_mute" width="198" height="199"/>
|
||||||
<image name="switchCameraButton" width="39" height="39"/>
|
<image name="mic_unmute" width="198" height="202"/>
|
||||||
<image name="switchCameraButtonSelected" width="39" height="39"/>
|
|
||||||
<image name="videoMuteButton" width="39" height="39"/>
|
|
||||||
<image name="videoMuteButtonSelected" width="39" height="39"/>
|
|
||||||
<image name="videoMutedIndicator" width="153.5" height="129"/>
|
<image name="videoMutedIndicator" width="153.5" height="129"/>
|
||||||
|
<image name="video_mute" width="202" height="199"/>
|
||||||
|
<image name="video_unmute" width="202" height="202"/>
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Extensions.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by Zohaib Iqbal Kambrani on 09/06/2021.
|
||||||
|
// Copyright © 2021 The Chromium Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
import AADraggableView
|
||||||
|
|
||||||
|
extension AADraggableView{
|
||||||
|
func enable(_ enable:Bool){
|
||||||
|
isEnabled = enable
|
||||||
|
if enable == false{
|
||||||
|
gestureRecognizers?.forEach({ gest in
|
||||||
|
removeGestureRecognizer(gest)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UIView{
|
||||||
|
func hidden(_ hidden:Bool, rootView:UIView){
|
||||||
|
UIView.transition(with: rootView, duration: 0.5, options: .transitionCrossDissolve, animations: {
|
||||||
|
self.isHidden = hidden
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,190 @@
|
|||||||
|
//
|
||||||
|
// MainAppViewController.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by Zohaib Iqbal Kambrani on 08/06/2021.
|
||||||
|
// Copyright © 2021 The Chromium Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import AADraggableView
|
||||||
|
|
||||||
|
class MainAppViewController: FlutterViewController{
|
||||||
|
var videoCallContainer:AADraggableView!
|
||||||
|
var videoCallViewController:VideoCallViewController!
|
||||||
|
var videoCallFlutterResult:FlutterResult?
|
||||||
|
var vdoCallViewFloatRectConstraint:[NSLayoutConstraint]!
|
||||||
|
var vdoCallViewFullConstraint:[NSLayoutConstraint]!
|
||||||
|
var vdoCallViewFloatCircleConstraint:[NSLayoutConstraint]!
|
||||||
|
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
initFlutterBridge()
|
||||||
|
prepareVideoCallView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
}
|
||||||
|
|
||||||
|
var videoCallChannel:FlutterMethodChannel?
|
||||||
|
private func initFlutterBridge(){
|
||||||
|
videoCallChannel = FlutterMethodChannel(name: "Dr.cloudSolution/videoCall", binaryMessenger: binaryMessenger)
|
||||||
|
videoCallChannel?.setMethodCallHandler({
|
||||||
|
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
|
||||||
|
switch call.method {
|
||||||
|
case "openVideoCall":
|
||||||
|
self.startVideoCall(result: result, call: call)
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Video Call Functions
|
||||||
|
extension MainAppViewController : ICallProtocol{
|
||||||
|
|
||||||
|
func prepareVideoCallView(){
|
||||||
|
videoCallContainer = AADraggableView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height))
|
||||||
|
videoCallContainer.backgroundColor = UIColor.black
|
||||||
|
videoCallContainer.isHidden = true
|
||||||
|
videoCallContainer.clipsToBounds = true
|
||||||
|
videoCallContainer.padding = 20
|
||||||
|
videoCallContainer.reposition = .edgesOnly
|
||||||
|
videoCallContainer.isEnabled = false
|
||||||
|
|
||||||
|
view.addSubview(videoCallContainer)
|
||||||
|
setVideoViewConstrints()
|
||||||
|
NSLayoutConstraint.activate(vdoCallViewFullConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(vdoCallViewFloatRectConstraint)
|
||||||
|
|
||||||
|
ViewEmbedder.embed(
|
||||||
|
withIdentifier: "videoCall", // Storyboard ID
|
||||||
|
parent: self,
|
||||||
|
container: self.videoCallContainer){ vc in
|
||||||
|
self.videoCallViewController = vc as? VideoCallViewController
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showVideo(show:Bool){
|
||||||
|
self.videoCallContainer.hidden(!show, rootView: view)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startVideoCall(result: @escaping FlutterResult, call:FlutterMethodCall) {
|
||||||
|
videoCallFlutterResult = result
|
||||||
|
|
||||||
|
if let arguments = call.arguments as? NSDictionary{
|
||||||
|
showVideoCallView(true)
|
||||||
|
|
||||||
|
videoCallViewController.onRectFloat = { isRectFloat in
|
||||||
|
self.rectFloatVideoCallView(isRectFloat)
|
||||||
|
}
|
||||||
|
|
||||||
|
videoCallViewController.onCircleFloat = { isCircleFloat in
|
||||||
|
self.circleFloatVideoCallView(isCircleFloat)
|
||||||
|
}
|
||||||
|
videoCallViewController.onCallConnect = {
|
||||||
|
self.videoCallChannel?.invokeMethod("onCallConnected",arguments: nil)
|
||||||
|
}
|
||||||
|
videoCallViewController.onCallDisconnect = {
|
||||||
|
self.showVideoCallView(false)
|
||||||
|
self.videoCallViewController.minimizeVideoState(state: false)
|
||||||
|
self.videoCallChannel?.invokeMethod("onCallDisconnected",arguments: nil)
|
||||||
|
}
|
||||||
|
videoCallViewController.callBack = self
|
||||||
|
videoCallViewController.start(params: VideoCallRequestParameters(dictionary: arguments))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func rectFloatVideoCallView(_ value:Bool){
|
||||||
|
videoCallContainer.enable(value)
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.5) {
|
||||||
|
if(value){
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
|
||||||
|
NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint)
|
||||||
|
}else{
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
|
||||||
|
NSLayoutConstraint.activate(self.vdoCallViewFullConstraint)
|
||||||
|
}
|
||||||
|
self.videoCallContainer.layer.cornerRadius = value ? 10 : 0
|
||||||
|
self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil
|
||||||
|
self.videoCallContainer.layer.borderWidth = value ? 2 : 0
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func circleFloatVideoCallView(_ value:Bool){
|
||||||
|
videoCallContainer.reposition = value ? .sticky : .edgesOnly
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.5) {
|
||||||
|
if(value){
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint)
|
||||||
|
NSLayoutConstraint.activate(self.vdoCallViewFloatCircleConstraint)
|
||||||
|
self.videoCallContainer.layer.cornerRadius = 35
|
||||||
|
}else{
|
||||||
|
NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint)
|
||||||
|
NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint)
|
||||||
|
self.videoCallContainer.layer.cornerRadius = 10
|
||||||
|
|
||||||
|
}
|
||||||
|
self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil
|
||||||
|
self.videoCallContainer.layer.borderWidth = value ? 2 : 0
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showVideoCallView(_ value:Bool){
|
||||||
|
self.videoCallContainer.hidden(!value, rootView: view)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionDone(res: Any) {
|
||||||
|
videoCallFlutterResult?(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionNotResponded(res: Any) {
|
||||||
|
videoCallFlutterResult?(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setVideoViewConstrints(){
|
||||||
|
videoCallContainer.layer.shadowColor = UIColor.black.cgColor
|
||||||
|
videoCallContainer.layer.shadowOffset = CGSize(width: 1, height: 1)
|
||||||
|
videoCallContainer.layer.shadowRadius = 5
|
||||||
|
|
||||||
|
let screen = UIScreen.main.bounds
|
||||||
|
|
||||||
|
videoCallContainer.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
vdoCallViewFullConstraint = [
|
||||||
|
videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
|
videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width),
|
||||||
|
videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height)
|
||||||
|
]
|
||||||
|
vdoCallViewFloatRectConstraint = [
|
||||||
|
videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40),
|
||||||
|
videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
|
||||||
|
videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width/3),
|
||||||
|
videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height/3.5)
|
||||||
|
]
|
||||||
|
vdoCallViewFloatCircleConstraint = [
|
||||||
|
videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40),
|
||||||
|
videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
|
||||||
|
videoCallContainer.widthAnchor.constraint(equalToConstant: 70),
|
||||||
|
videoCallContainer.heightAnchor.constraint(equalToConstant: 70)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// VCEmbeder.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by Zohaib Iqbal Kambrani on 08/06/2021.
|
||||||
|
// Copyright © 2021 The Chromium Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension UIView {
|
||||||
|
func fill(to parent: UIView, animateDuration:Double = 0.5) {
|
||||||
|
self.topAnchor.constraint(equalTo: parent.topAnchor).isActive = true
|
||||||
|
self.leadingAnchor.constraint(equalTo: parent.leadingAnchor).isActive = true
|
||||||
|
self.bottomAnchor.constraint(equalTo: parent.bottomAnchor).isActive = true
|
||||||
|
self.trailingAnchor.constraint(equalTo: parent.trailingAnchor).isActive = true
|
||||||
|
UIView.animate(withDuration: animateDuration) {
|
||||||
|
parent.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillToParent(animateDuration:Double = 0.5) {
|
||||||
|
if let parent = self.superview{
|
||||||
|
self.topAnchor.constraint(equalTo: parent.topAnchor).isActive = true
|
||||||
|
self.leadingAnchor.constraint(equalTo: parent.leadingAnchor).isActive = true
|
||||||
|
self.bottomAnchor.constraint(equalTo: parent.bottomAnchor).isActive = true
|
||||||
|
self.trailingAnchor.constraint(equalTo: parent.trailingAnchor).isActive = true
|
||||||
|
UIView.animate(withDuration: animateDuration) {
|
||||||
|
parent.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillInTo(view:UIView) {
|
||||||
|
view.addSubview(self)
|
||||||
|
fillToParent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewEmbedder {
|
||||||
|
class func embed(
|
||||||
|
parent:UIViewController,
|
||||||
|
container:UIView,
|
||||||
|
child:UIViewController,
|
||||||
|
previous:UIViewController?){
|
||||||
|
|
||||||
|
if let previous = previous {
|
||||||
|
removeFromParent(vc: previous)
|
||||||
|
}
|
||||||
|
child.willMove(toParent: parent)
|
||||||
|
parent.addChild(child)
|
||||||
|
container.addSubview(child.view)
|
||||||
|
child.didMove(toParent: parent)
|
||||||
|
let w = container.frame.size.width;
|
||||||
|
let h = container.frame.size.height;
|
||||||
|
child.view.frame = CGRect(x: 0, y: 0, width: w, height: h)
|
||||||
|
child.view.backgroundColor = UIColor.black
|
||||||
|
|
||||||
|
child.view.fill(to: container)
|
||||||
|
}
|
||||||
|
|
||||||
|
class func removeFromParent(vc:UIViewController){
|
||||||
|
vc.willMove(toParent: nil)
|
||||||
|
vc.view.removeFromSuperview()
|
||||||
|
vc.removeFromParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
class func embed(withIdentifier id:String, parent:UIViewController, container:UIView, completion:((UIViewController)->Void)? = nil){
|
||||||
|
let vc = parent.storyboard!.instantiateViewController(withIdentifier: id)
|
||||||
|
embed(
|
||||||
|
parent: parent,
|
||||||
|
container: container,
|
||||||
|
child: vc,
|
||||||
|
previous: parent.children.first
|
||||||
|
)
|
||||||
|
completion?(vc)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class VideoCallRequestParameters{
|
||||||
|
var apiKey:String?
|
||||||
|
var sessionId:String?
|
||||||
|
var token:String?
|
||||||
|
var lang:String?
|
||||||
|
var vcId:Int?
|
||||||
|
var tokenId:String?
|
||||||
|
var generalId:String?
|
||||||
|
var doctorId:Int?
|
||||||
|
var baseUrl:String?
|
||||||
|
var patientName:String?
|
||||||
|
|
||||||
|
init(dictionary:NSDictionary){
|
||||||
|
self.apiKey = dictionary["kApiKey"] as? String
|
||||||
|
self.sessionId = dictionary["kSessionId"] as? String
|
||||||
|
self.token = dictionary["kToken"] as? String
|
||||||
|
self.lang = dictionary["appLang"] as? String
|
||||||
|
self.vcId = dictionary["VC_ID"] as? Int
|
||||||
|
self.tokenId = dictionary["TokenID"] as? String
|
||||||
|
self.generalId = dictionary["generalId"] as? String
|
||||||
|
self.doctorId = dictionary["DoctorId"] as? Int
|
||||||
|
self.baseUrl = dictionary["baseUrl"] as? String
|
||||||
|
self.patientName = dictionary["patientName"] as? String
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
enum PatientType{
|
||||||
|
IN_PATIENT,
|
||||||
|
OUT_PATIENT,
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
enum AuthMethodTypes { SMS, WhatsApp, Fingerprint,FaceID,MoreOptions }
|
||||||
|
extension SelectedAuthMethodTypesService on AuthMethodTypes {
|
||||||
|
// ignore: missing_return
|
||||||
|
int getTypeIdService() {
|
||||||
|
switch (this) {
|
||||||
|
case AuthMethodTypes.SMS:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case AuthMethodTypes.WhatsApp:
|
||||||
|
return 2;
|
||||||
|
break;
|
||||||
|
case AuthMethodTypes.Fingerprint:
|
||||||
|
return 3;
|
||||||
|
break;
|
||||||
|
case AuthMethodTypes.FaceID:
|
||||||
|
return 4;
|
||||||
|
break;
|
||||||
|
case AuthMethodTypes.MoreOptions:
|
||||||
|
return 5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore: missing_return
|
||||||
|
static getMethodsTypeService( int typeId) {
|
||||||
|
switch (typeId) {
|
||||||
|
case 1:
|
||||||
|
return AuthMethodTypes.SMS;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return AuthMethodTypes.WhatsApp;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return AuthMethodTypes.Fingerprint;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
return AuthMethodTypes.FaceID;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
return AuthMethodTypes.MoreOptions;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,192 @@
|
|||||||
|
import 'package:doctor_app_flutter/models/doctor/doctor_profile_model.dart';
|
||||||
|
|
||||||
|
class CheckActivationCodeForDoctorAppResponseModel {
|
||||||
|
String authenticationTokenID;
|
||||||
|
List<ListDoctorsClinic> listDoctorsClinic;
|
||||||
|
List<DoctorProfileModel> listDoctorProfile;
|
||||||
|
MemberInformation memberInformation;
|
||||||
|
|
||||||
|
CheckActivationCodeForDoctorAppResponseModel(
|
||||||
|
{this.authenticationTokenID,
|
||||||
|
this.listDoctorsClinic,
|
||||||
|
this.memberInformation});
|
||||||
|
|
||||||
|
CheckActivationCodeForDoctorAppResponseModel.fromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
authenticationTokenID = json['AuthenticationTokenID'];
|
||||||
|
if (json['List_DoctorsClinic'] != null) {
|
||||||
|
listDoctorsClinic = new List<ListDoctorsClinic>();
|
||||||
|
json['List_DoctorsClinic'].forEach((v) {
|
||||||
|
listDoctorsClinic.add(new ListDoctorsClinic.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json['List_DoctorProfile'] != null) {
|
||||||
|
listDoctorProfile = new List<DoctorProfileModel>();
|
||||||
|
json['List_DoctorProfile'].forEach((v) {
|
||||||
|
listDoctorProfile.add(new DoctorProfileModel.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
memberInformation = json['memberInformation'] != null
|
||||||
|
? new MemberInformation.fromJson(json['memberInformation'])
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['AuthenticationTokenID'] = this.authenticationTokenID;
|
||||||
|
if (this.listDoctorsClinic != null) {
|
||||||
|
data['List_DoctorsClinic'] =
|
||||||
|
this.listDoctorsClinic.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.listDoctorProfile != null) {
|
||||||
|
data['List_DoctorProfile'] =
|
||||||
|
this.listDoctorProfile.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
if (this.memberInformation != null) {
|
||||||
|
data['memberInformation'] = this.memberInformation.toJson();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListDoctorsClinic {
|
||||||
|
Null setupID;
|
||||||
|
int projectID;
|
||||||
|
int doctorID;
|
||||||
|
int clinicID;
|
||||||
|
bool isActive;
|
||||||
|
String clinicName;
|
||||||
|
|
||||||
|
ListDoctorsClinic({this.setupID,
|
||||||
|
this.projectID,
|
||||||
|
this.doctorID,
|
||||||
|
this.clinicID,
|
||||||
|
this.isActive,
|
||||||
|
this.clinicName});
|
||||||
|
|
||||||
|
ListDoctorsClinic.fromJson(Map<String, dynamic> json) {
|
||||||
|
setupID = json['SetupID'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
isActive = json['IsActive'];
|
||||||
|
clinicName = json['ClinicName'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['SetupID'] = this.setupID;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['IsActive'] = this.isActive;
|
||||||
|
data['ClinicName'] = this.clinicName;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemberInformation {
|
||||||
|
List<Clinics> clinics;
|
||||||
|
int doctorId;
|
||||||
|
String email;
|
||||||
|
int employeeId;
|
||||||
|
int memberId;
|
||||||
|
Null memberName;
|
||||||
|
Null memberNameArabic;
|
||||||
|
String preferredLanguage;
|
||||||
|
List<Roles> roles;
|
||||||
|
|
||||||
|
MemberInformation({this.clinics,
|
||||||
|
this.doctorId,
|
||||||
|
this.email,
|
||||||
|
this.employeeId,
|
||||||
|
this.memberId,
|
||||||
|
this.memberName,
|
||||||
|
this.memberNameArabic,
|
||||||
|
this.preferredLanguage,
|
||||||
|
this.roles});
|
||||||
|
|
||||||
|
MemberInformation.fromJson(Map<String, dynamic> json) {
|
||||||
|
if (json['clinics'] != null) {
|
||||||
|
clinics = new List<Clinics>();
|
||||||
|
json['clinics'].forEach((v) {
|
||||||
|
clinics.add(new Clinics.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
doctorId = json['doctorId'];
|
||||||
|
email = json['email'];
|
||||||
|
employeeId = json['employeeId'];
|
||||||
|
memberId = json['memberId'];
|
||||||
|
memberName = json['memberName'];
|
||||||
|
memberNameArabic = json['memberNameArabic'];
|
||||||
|
preferredLanguage = json['preferredLanguage'];
|
||||||
|
if (json['roles'] != null) {
|
||||||
|
roles = new List<Roles>();
|
||||||
|
json['roles'].forEach((v) {
|
||||||
|
roles.add(new Roles.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
if (this.clinics != null) {
|
||||||
|
data['clinics'] = this.clinics.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
data['doctorId'] = this.doctorId;
|
||||||
|
data['email'] = this.email;
|
||||||
|
data['employeeId'] = this.employeeId;
|
||||||
|
data['memberId'] = this.memberId;
|
||||||
|
data['memberName'] = this.memberName;
|
||||||
|
data['memberNameArabic'] = this.memberNameArabic;
|
||||||
|
data['preferredLanguage'] = this.preferredLanguage;
|
||||||
|
if (this.roles != null) {
|
||||||
|
data['roles'] = this.roles.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Clinics {
|
||||||
|
bool defaultClinic;
|
||||||
|
int id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
Clinics({this.defaultClinic, this.id, this.name});
|
||||||
|
|
||||||
|
Clinics.fromJson(Map<String, dynamic> json) {
|
||||||
|
defaultClinic = json['defaultClinic'];
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['defaultClinic'] = this.defaultClinic;
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Roles {
|
||||||
|
String name;
|
||||||
|
int roleId;
|
||||||
|
|
||||||
|
Roles({this.name, this.roleId});
|
||||||
|
|
||||||
|
Roles.fromJson(Map<String, dynamic> json) {
|
||||||
|
name = json['name'];
|
||||||
|
roleId = json['roleId'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['name'] = this.name;
|
||||||
|
data['roleId'] = this.roleId;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
class NewLoginInformationModel {
|
||||||
|
int doctorID;
|
||||||
|
List<ListMemberInformation> listMemberInformation;
|
||||||
|
String logInTokenID;
|
||||||
|
String mobileNumber;
|
||||||
|
Null sELECTDeviceIMEIbyIMEIList;
|
||||||
|
int userID;
|
||||||
|
String zipCode;
|
||||||
|
bool isActiveCode;
|
||||||
|
bool isSMSSent;
|
||||||
|
|
||||||
|
NewLoginInformationModel(
|
||||||
|
{this.doctorID,
|
||||||
|
this.listMemberInformation,
|
||||||
|
this.logInTokenID,
|
||||||
|
this.mobileNumber,
|
||||||
|
this.sELECTDeviceIMEIbyIMEIList,
|
||||||
|
this.userID,
|
||||||
|
this.zipCode,
|
||||||
|
this.isActiveCode,
|
||||||
|
this.isSMSSent});
|
||||||
|
|
||||||
|
NewLoginInformationModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
if (json['List_MemberInformation'] != null) {
|
||||||
|
listMemberInformation = new List<ListMemberInformation>();
|
||||||
|
json['List_MemberInformation'].forEach((v) {
|
||||||
|
listMemberInformation.add(new ListMemberInformation.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
logInTokenID = json['LogInTokenID'];
|
||||||
|
mobileNumber = json['MobileNumber'];
|
||||||
|
sELECTDeviceIMEIbyIMEIList = json['SELECTDeviceIMEIbyIMEI_List'];
|
||||||
|
userID = json['UserID'];
|
||||||
|
zipCode = json['ZipCode'];
|
||||||
|
isActiveCode = json['isActiveCode'];
|
||||||
|
isSMSSent = json['isSMSSent'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
if (this.listMemberInformation != null) {
|
||||||
|
data['List_MemberInformation'] =
|
||||||
|
this.listMemberInformation.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
data['LogInTokenID'] = this.logInTokenID;
|
||||||
|
data['MobileNumber'] = this.mobileNumber;
|
||||||
|
data['SELECTDeviceIMEIbyIMEI_List'] = this.sELECTDeviceIMEIbyIMEIList;
|
||||||
|
data['UserID'] = this.userID;
|
||||||
|
data['ZipCode'] = this.zipCode;
|
||||||
|
data['isActiveCode'] = this.isActiveCode;
|
||||||
|
data['isSMSSent'] = this.isSMSSent;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListMemberInformation {
|
||||||
|
Null setupID;
|
||||||
|
int memberID;
|
||||||
|
String memberName;
|
||||||
|
Null memberNameN;
|
||||||
|
String preferredLang;
|
||||||
|
String pIN;
|
||||||
|
String saltHash;
|
||||||
|
int referenceID;
|
||||||
|
int employeeID;
|
||||||
|
int roleID;
|
||||||
|
int projectid;
|
||||||
|
|
||||||
|
ListMemberInformation(
|
||||||
|
{this.setupID,
|
||||||
|
this.memberID,
|
||||||
|
this.memberName,
|
||||||
|
this.memberNameN,
|
||||||
|
this.preferredLang,
|
||||||
|
this.pIN,
|
||||||
|
this.saltHash,
|
||||||
|
this.referenceID,
|
||||||
|
this.employeeID,
|
||||||
|
this.roleID,
|
||||||
|
this.projectid});
|
||||||
|
|
||||||
|
ListMemberInformation.fromJson(Map<String, dynamic> json) {
|
||||||
|
setupID = json['SetupID'];
|
||||||
|
memberID = json['MemberID'];
|
||||||
|
memberName = json['MemberName'];
|
||||||
|
memberNameN = json['MemberNameN'];
|
||||||
|
preferredLang = json['PreferredLang'];
|
||||||
|
pIN = json['PIN'];
|
||||||
|
saltHash = json['SaltHash'];
|
||||||
|
referenceID = json['ReferenceID'];
|
||||||
|
employeeID = json['EmployeeID'];
|
||||||
|
roleID = json['RoleID'];
|
||||||
|
projectid = json['projectid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['SetupID'] = this.setupID;
|
||||||
|
data['MemberID'] = this.memberID;
|
||||||
|
data['MemberName'] = this.memberName;
|
||||||
|
data['MemberNameN'] = this.memberNameN;
|
||||||
|
data['PreferredLang'] = this.preferredLang;
|
||||||
|
data['PIN'] = this.pIN;
|
||||||
|
data['SaltHash'] = this.saltHash;
|
||||||
|
data['ReferenceID'] = this.referenceID;
|
||||||
|
data['EmployeeID'] = this.employeeID;
|
||||||
|
data['RoleID'] = this.roleID;
|
||||||
|
data['projectid'] = this.projectid;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
class SendActivationCodeForDoctorAppResponseModel {
|
||||||
|
String logInTokenID;
|
||||||
|
String verificationCode;
|
||||||
|
String vidaAuthTokenID;
|
||||||
|
String vidaRefreshTokenID;
|
||||||
|
|
||||||
|
SendActivationCodeForDoctorAppResponseModel(
|
||||||
|
{this.logInTokenID,
|
||||||
|
this.verificationCode,
|
||||||
|
this.vidaAuthTokenID,
|
||||||
|
this.vidaRefreshTokenID});
|
||||||
|
|
||||||
|
SendActivationCodeForDoctorAppResponseModel.fromJson(
|
||||||
|
Map<String, dynamic> json) {
|
||||||
|
logInTokenID = json['LogInTokenID'];
|
||||||
|
verificationCode = json['VerificationCode'];
|
||||||
|
vidaAuthTokenID = json['VidaAuthTokenID'];
|
||||||
|
vidaRefreshTokenID = json['VidaRefreshTokenID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['LogInTokenID'] = this.logInTokenID;
|
||||||
|
data['VerificationCode'] = this.verificationCode;
|
||||||
|
data['VidaAuthTokenID'] = this.vidaAuthTokenID;
|
||||||
|
data['VidaRefreshTokenID'] = this.vidaRefreshTokenID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
class GetHospitalsRequestModel {
|
||||||
|
int languageID;
|
||||||
|
String stamp;
|
||||||
|
String iPAdress;
|
||||||
|
double versionID;
|
||||||
|
int channel;
|
||||||
|
String tokenID;
|
||||||
|
String sessionID;
|
||||||
|
bool isLoginForDoctorApp;
|
||||||
|
String memberID;
|
||||||
|
|
||||||
|
GetHospitalsRequestModel(
|
||||||
|
{this.languageID,
|
||||||
|
this.stamp,
|
||||||
|
this.iPAdress,
|
||||||
|
this.versionID,
|
||||||
|
this.channel,
|
||||||
|
this.tokenID,
|
||||||
|
this.sessionID,
|
||||||
|
this.isLoginForDoctorApp,
|
||||||
|
this.memberID});
|
||||||
|
|
||||||
|
GetHospitalsRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
languageID = json['LanguageID'];
|
||||||
|
stamp = json['stamp'];
|
||||||
|
iPAdress = json['IPAdress'];
|
||||||
|
versionID = json['VersionID'];
|
||||||
|
channel = json['Channel'];
|
||||||
|
tokenID = json['TokenID'];
|
||||||
|
sessionID = json['SessionID'];
|
||||||
|
isLoginForDoctorApp = json['IsLoginForDoctorApp'];
|
||||||
|
memberID = json['MemberID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['LanguageID'] = this.languageID;
|
||||||
|
data['stamp'] = this.stamp;
|
||||||
|
data['IPAdress'] = this.iPAdress;
|
||||||
|
data['VersionID'] = this.versionID;
|
||||||
|
data['Channel'] = this.channel;
|
||||||
|
data['TokenID'] = this.tokenID;
|
||||||
|
data['SessionID'] = this.sessionID;
|
||||||
|
data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
|
||||||
|
data['MemberID'] = this.memberID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
class GetHospitalsResponseModel {
|
||||||
|
String facilityGroupId;
|
||||||
|
int facilityId;
|
||||||
|
String facilityName;
|
||||||
|
|
||||||
|
GetHospitalsResponseModel(
|
||||||
|
{this.facilityGroupId, this.facilityId, this.facilityName});
|
||||||
|
|
||||||
|
GetHospitalsResponseModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
facilityGroupId = json['facilityGroupId'];
|
||||||
|
facilityId = json['facilityId'];
|
||||||
|
facilityName = json['facilityName'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['facilityGroupId'] = this.facilityGroupId;
|
||||||
|
data['facilityId'] = this.facilityId;
|
||||||
|
data['facilityName'] = this.facilityName;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class AlternativeService {
|
||||||
|
int serviceID;
|
||||||
|
String serviceName;
|
||||||
|
bool isSelected;
|
||||||
|
|
||||||
|
AlternativeService(
|
||||||
|
{this.serviceID, this.serviceName, this.isSelected = false});
|
||||||
|
|
||||||
|
AlternativeService.fromJson(Map<String, dynamic> json) {
|
||||||
|
serviceID = json['ServicID'];
|
||||||
|
serviceName = json['ServiceName'];
|
||||||
|
isSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['ServicID'] = this.serviceID;
|
||||||
|
data['ServiceName'] = this.serviceName;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AlternativeServicesList with ChangeNotifier {
|
||||||
|
List<AlternativeService> _alternativeServicesList;
|
||||||
|
|
||||||
|
getServicesList(){
|
||||||
|
return _alternativeServicesList;
|
||||||
|
}
|
||||||
|
|
||||||
|
setServicesList(List<AlternativeService> alternativeServicesList) {
|
||||||
|
this._alternativeServicesList = alternativeServicesList;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelected(AlternativeService service, bool isSelected) {
|
||||||
|
List<AlternativeService> alternativeService = _alternativeServicesList.where((element) => service.serviceID == element.serviceID).toList();
|
||||||
|
|
||||||
|
alternativeService[0].isSelected = isSelected;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
class PendingPatientERForDoctorAppRequestModel {
|
||||||
|
bool outSA;
|
||||||
|
int doctorID;
|
||||||
|
String sErServiceID;
|
||||||
|
|
||||||
|
PendingPatientERForDoctorAppRequestModel(
|
||||||
|
{this.outSA, this.doctorID, this.sErServiceID});
|
||||||
|
|
||||||
|
PendingPatientERForDoctorAppRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
outSA = json['OutSA'];
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
sErServiceID = json['SErServiceID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['OutSA'] = this.outSA;
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['SErServiceID'] = this.sErServiceID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
class LiveCareUserLoginRequestModel {
|
||||||
|
String tokenID;
|
||||||
|
String generalid;
|
||||||
|
int doctorId;
|
||||||
|
int isOutKsa;
|
||||||
|
int isLogin;
|
||||||
|
|
||||||
|
LiveCareUserLoginRequestModel({this.tokenID, this.generalid, this.doctorId, this.isOutKsa, this.isLogin});
|
||||||
|
|
||||||
|
LiveCareUserLoginRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
tokenID = json['TokenID'];
|
||||||
|
generalid = json['generalid'];
|
||||||
|
doctorId = json['DoctorId'];
|
||||||
|
isOutKsa = json['IsOutKsa'];
|
||||||
|
isLogin = json['IsLogin'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['TokenID'] = this.tokenID;
|
||||||
|
data['generalid'] = this.generalid;
|
||||||
|
data['DoctorId'] = this.doctorId;
|
||||||
|
data['IsOutKsa'] = this.isOutKsa;
|
||||||
|
data['IsLogin'] = this.isLogin;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
class ProcedureTempleteRequestModel {
|
||||||
|
int doctorID;
|
||||||
|
String firstName;
|
||||||
|
String middleName;
|
||||||
|
String lastName;
|
||||||
|
String patientMobileNumber;
|
||||||
|
String patientIdentificationID;
|
||||||
|
int patientID;
|
||||||
|
String from;
|
||||||
|
String to;
|
||||||
|
int searchType;
|
||||||
|
String mobileNo;
|
||||||
|
String identificationNo;
|
||||||
|
int editedBy;
|
||||||
|
int projectID;
|
||||||
|
int clinicID;
|
||||||
|
String tokenID;
|
||||||
|
int languageID;
|
||||||
|
String stamp;
|
||||||
|
String iPAdress;
|
||||||
|
double versionID;
|
||||||
|
int channel;
|
||||||
|
String sessionID;
|
||||||
|
bool isLoginForDoctorApp;
|
||||||
|
bool patientOutSA;
|
||||||
|
String vidaAuthTokenID;
|
||||||
|
String vidaRefreshTokenID;
|
||||||
|
int deviceTypeID;
|
||||||
|
|
||||||
|
ProcedureTempleteRequestModel(
|
||||||
|
{this.doctorID,
|
||||||
|
this.firstName,
|
||||||
|
this.middleName,
|
||||||
|
this.lastName,
|
||||||
|
this.patientMobileNumber,
|
||||||
|
this.patientIdentificationID,
|
||||||
|
this.patientID,
|
||||||
|
this.from,
|
||||||
|
this.to,
|
||||||
|
this.searchType,
|
||||||
|
this.mobileNo,
|
||||||
|
this.identificationNo,
|
||||||
|
this.editedBy,
|
||||||
|
this.projectID,
|
||||||
|
this.clinicID,
|
||||||
|
this.tokenID,
|
||||||
|
this.languageID,
|
||||||
|
this.stamp,
|
||||||
|
this.iPAdress,
|
||||||
|
this.versionID,
|
||||||
|
this.channel,
|
||||||
|
this.sessionID,
|
||||||
|
this.isLoginForDoctorApp,
|
||||||
|
this.patientOutSA,
|
||||||
|
this.vidaAuthTokenID,
|
||||||
|
this.vidaRefreshTokenID,
|
||||||
|
this.deviceTypeID});
|
||||||
|
|
||||||
|
ProcedureTempleteRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
firstName = json['FirstName'];
|
||||||
|
middleName = json['MiddleName'];
|
||||||
|
lastName = json['LastName'];
|
||||||
|
patientMobileNumber = json['PatientMobileNumber'];
|
||||||
|
patientIdentificationID = json['PatientIdentificationID'];
|
||||||
|
patientID = json['PatientID'];
|
||||||
|
from = json['From'];
|
||||||
|
to = json['To'];
|
||||||
|
searchType = json['SearchType'];
|
||||||
|
mobileNo = json['MobileNo'];
|
||||||
|
identificationNo = json['IdentificationNo'];
|
||||||
|
editedBy = json['EditedBy'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
tokenID = json['TokenID'];
|
||||||
|
languageID = json['LanguageID'];
|
||||||
|
stamp = json['stamp'];
|
||||||
|
iPAdress = json['IPAdress'];
|
||||||
|
versionID = json['VersionID'];
|
||||||
|
channel = json['Channel'];
|
||||||
|
sessionID = json['SessionID'];
|
||||||
|
isLoginForDoctorApp = json['IsLoginForDoctorApp'];
|
||||||
|
patientOutSA = json['PatientOutSA'];
|
||||||
|
vidaAuthTokenID = json['VidaAuthTokenID'];
|
||||||
|
vidaRefreshTokenID = json['VidaRefreshTokenID'];
|
||||||
|
deviceTypeID = json['DeviceTypeID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['FirstName'] = this.firstName;
|
||||||
|
data['MiddleName'] = this.middleName;
|
||||||
|
data['LastName'] = this.lastName;
|
||||||
|
data['PatientMobileNumber'] = this.patientMobileNumber;
|
||||||
|
data['PatientIdentificationID'] = this.patientIdentificationID;
|
||||||
|
data['PatientID'] = this.patientID;
|
||||||
|
data['From'] = this.from;
|
||||||
|
data['To'] = this.to;
|
||||||
|
data['SearchType'] = this.searchType;
|
||||||
|
data['MobileNo'] = this.mobileNo;
|
||||||
|
data['IdentificationNo'] = this.identificationNo;
|
||||||
|
data['EditedBy'] = this.editedBy;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['TokenID'] = this.tokenID;
|
||||||
|
data['LanguageID'] = this.languageID;
|
||||||
|
data['stamp'] = this.stamp;
|
||||||
|
data['IPAdress'] = this.iPAdress;
|
||||||
|
data['VersionID'] = this.versionID;
|
||||||
|
data['Channel'] = this.channel;
|
||||||
|
data['SessionID'] = this.sessionID;
|
||||||
|
data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
|
||||||
|
data['PatientOutSA'] = this.patientOutSA;
|
||||||
|
data['VidaAuthTokenID'] = this.vidaAuthTokenID;
|
||||||
|
data['VidaRefreshTokenID'] = this.vidaRefreshTokenID;
|
||||||
|
data['DeviceTypeID'] = this.deviceTypeID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
class ProcedureTempleteModel {
|
||||||
|
String setupID;
|
||||||
|
int projectID;
|
||||||
|
int clinicID;
|
||||||
|
int doctorID;
|
||||||
|
int templateID;
|
||||||
|
String templateName;
|
||||||
|
bool isActive;
|
||||||
|
int createdBy;
|
||||||
|
String createdOn;
|
||||||
|
dynamic editedBy;
|
||||||
|
dynamic editedOn;
|
||||||
|
|
||||||
|
ProcedureTempleteModel(
|
||||||
|
{this.setupID,
|
||||||
|
this.projectID,
|
||||||
|
this.clinicID,
|
||||||
|
this.doctorID,
|
||||||
|
this.templateID,
|
||||||
|
this.templateName,
|
||||||
|
this.isActive,
|
||||||
|
this.createdBy,
|
||||||
|
this.createdOn,
|
||||||
|
this.editedBy,
|
||||||
|
this.editedOn});
|
||||||
|
|
||||||
|
ProcedureTempleteModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
setupID = json['SetupID'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
templateID = json['TemplateID'];
|
||||||
|
templateName = json['TemplateName'];
|
||||||
|
isActive = json['IsActive'];
|
||||||
|
createdBy = json['CreatedBy'];
|
||||||
|
createdOn = json['CreatedOn'];
|
||||||
|
editedBy = json['EditedBy'];
|
||||||
|
editedOn = json['EditedOn'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['SetupID'] = this.setupID;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['TemplateID'] = this.templateID;
|
||||||
|
data['TemplateName'] = this.templateName;
|
||||||
|
data['IsActive'] = this.isActive;
|
||||||
|
data['CreatedBy'] = this.createdBy;
|
||||||
|
data['CreatedOn'] = this.createdOn;
|
||||||
|
data['EditedBy'] = this.editedBy;
|
||||||
|
data['EditedOn'] = this.editedOn;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
class ProcedureTempleteDetailsModel {
|
||||||
|
String setupID;
|
||||||
|
int projectID;
|
||||||
|
int clinicID;
|
||||||
|
int doctorID;
|
||||||
|
int templateID;
|
||||||
|
String templateName;
|
||||||
|
String procedureID;
|
||||||
|
bool isActive;
|
||||||
|
int createdBy;
|
||||||
|
String createdOn;
|
||||||
|
dynamic editedBy;
|
||||||
|
dynamic editedOn;
|
||||||
|
String procedureName;
|
||||||
|
String procedureNameN;
|
||||||
|
String alias;
|
||||||
|
String aliasN;
|
||||||
|
String categoryID;
|
||||||
|
String subGroupID;
|
||||||
|
String categoryDescription;
|
||||||
|
String categoryDescriptionN;
|
||||||
|
String categoryAlias;
|
||||||
|
dynamic riskCategoryID;
|
||||||
|
String type = "1";
|
||||||
|
String remarks;
|
||||||
|
int selectedType = 0;
|
||||||
|
|
||||||
|
ProcedureTempleteDetailsModel(
|
||||||
|
{this.setupID,
|
||||||
|
this.projectID,
|
||||||
|
this.clinicID,
|
||||||
|
this.doctorID,
|
||||||
|
this.templateID,
|
||||||
|
this.procedureID,
|
||||||
|
this.isActive,
|
||||||
|
this.createdBy,
|
||||||
|
this.createdOn,
|
||||||
|
this.editedBy,
|
||||||
|
this.editedOn,
|
||||||
|
this.procedureName,
|
||||||
|
this.procedureNameN,
|
||||||
|
this.alias,
|
||||||
|
this.aliasN,
|
||||||
|
this.categoryID,
|
||||||
|
this.subGroupID,
|
||||||
|
this.riskCategoryID,
|
||||||
|
this.templateName,
|
||||||
|
this.categoryDescription,
|
||||||
|
this.categoryDescriptionN,
|
||||||
|
this.categoryAlias,
|
||||||
|
this.remarks,
|
||||||
|
this.type = "1",
|
||||||
|
this.selectedType = 0});
|
||||||
|
|
||||||
|
ProcedureTempleteDetailsModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
setupID = json['SetupID'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
templateID = json['TemplateID'];
|
||||||
|
procedureID = json['ProcedureID'];
|
||||||
|
isActive = json['IsActive'];
|
||||||
|
createdBy = json['CreatedBy'];
|
||||||
|
createdOn = json['CreatedOn'];
|
||||||
|
editedBy = json['EditedBy'];
|
||||||
|
editedOn = json['EditedOn'];
|
||||||
|
procedureName = json['ProcedureName'];
|
||||||
|
procedureNameN = json['ProcedureNameN'];
|
||||||
|
alias = json['Alias'];
|
||||||
|
aliasN = json['AliasN'];
|
||||||
|
categoryID = json['CategoryID'];
|
||||||
|
subGroupID = json['SubGroupID'];
|
||||||
|
riskCategoryID = json['RiskCategoryID'];
|
||||||
|
templateName = json['TemplateName'];
|
||||||
|
categoryDescription = json['CategoryDescription'];
|
||||||
|
categoryDescriptionN = json['CategoryDescriptionN'];
|
||||||
|
categoryAlias = json['CategoryAlias'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['SetupID'] = this.setupID;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['TemplateID'] = this.templateID;
|
||||||
|
data['ProcedureID'] = this.procedureID;
|
||||||
|
data['IsActive'] = this.isActive;
|
||||||
|
data['CreatedBy'] = this.createdBy;
|
||||||
|
data['CreatedOn'] = this.createdOn;
|
||||||
|
data['EditedBy'] = this.editedBy;
|
||||||
|
data['EditedOn'] = this.editedOn;
|
||||||
|
data['ProcedureName'] = this.procedureName;
|
||||||
|
data['ProcedureNameN'] = this.procedureNameN;
|
||||||
|
data['Alias'] = this.alias;
|
||||||
|
data['AliasN'] = this.aliasN;
|
||||||
|
data['CategoryID'] = this.categoryID;
|
||||||
|
data['SubGroupID'] = this.subGroupID;
|
||||||
|
data['RiskCategoryID'] = this.riskCategoryID;
|
||||||
|
data['TemplateName'] = this.templateName;
|
||||||
|
data['CategoryDescription'] = this.categoryDescription;
|
||||||
|
data['CategoryDescriptionN'] = this.categoryDescriptionN;
|
||||||
|
data['CategoryAlias'] = this.categoryAlias;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ProcedureTempleteDetailsModelList {
|
||||||
|
List<ProcedureTempleteDetailsModel> procedureTemplate = List();
|
||||||
|
String templateName;
|
||||||
|
int templateId;
|
||||||
|
|
||||||
|
ProcedureTempleteDetailsModelList(
|
||||||
|
{this.templateName, this.templateId, ProcedureTempleteDetailsModel template}) {
|
||||||
|
procedureTemplate.add(template);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
class ProcedureTempleteDetailsRequestModel {
|
||||||
|
int doctorID;
|
||||||
|
String firstName;
|
||||||
|
int templateID;
|
||||||
|
String middleName;
|
||||||
|
String lastName;
|
||||||
|
String patientMobileNumber;
|
||||||
|
String patientIdentificationID;
|
||||||
|
int patientID;
|
||||||
|
String from;
|
||||||
|
String to;
|
||||||
|
int searchType;
|
||||||
|
String mobileNo;
|
||||||
|
String identificationNo;
|
||||||
|
int editedBy;
|
||||||
|
int projectID;
|
||||||
|
int clinicID;
|
||||||
|
String tokenID;
|
||||||
|
int languageID;
|
||||||
|
String stamp;
|
||||||
|
String iPAdress;
|
||||||
|
double versionID;
|
||||||
|
int channel;
|
||||||
|
String sessionID;
|
||||||
|
bool isLoginForDoctorApp;
|
||||||
|
bool patientOutSA;
|
||||||
|
String vidaAuthTokenID;
|
||||||
|
String vidaRefreshTokenID;
|
||||||
|
int deviceTypeID;
|
||||||
|
|
||||||
|
ProcedureTempleteDetailsRequestModel(
|
||||||
|
{this.doctorID,
|
||||||
|
this.firstName,
|
||||||
|
this.templateID,
|
||||||
|
this.middleName,
|
||||||
|
this.lastName,
|
||||||
|
this.patientMobileNumber,
|
||||||
|
this.patientIdentificationID,
|
||||||
|
this.patientID,
|
||||||
|
this.from,
|
||||||
|
this.to,
|
||||||
|
this.searchType,
|
||||||
|
this.mobileNo,
|
||||||
|
this.identificationNo,
|
||||||
|
this.editedBy,
|
||||||
|
this.projectID,
|
||||||
|
this.clinicID,
|
||||||
|
this.tokenID,
|
||||||
|
this.languageID,
|
||||||
|
this.stamp,
|
||||||
|
this.iPAdress,
|
||||||
|
this.versionID,
|
||||||
|
this.channel,
|
||||||
|
this.sessionID,
|
||||||
|
this.isLoginForDoctorApp,
|
||||||
|
this.patientOutSA,
|
||||||
|
this.vidaAuthTokenID,
|
||||||
|
this.vidaRefreshTokenID,
|
||||||
|
this.deviceTypeID});
|
||||||
|
|
||||||
|
ProcedureTempleteDetailsRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
firstName = json['FirstName'];
|
||||||
|
templateID = json['TemplateID'];
|
||||||
|
middleName = json['MiddleName'];
|
||||||
|
lastName = json['LastName'];
|
||||||
|
patientMobileNumber = json['PatientMobileNumber'];
|
||||||
|
patientIdentificationID = json['PatientIdentificationID'];
|
||||||
|
patientID = json['PatientID'];
|
||||||
|
from = json['From'];
|
||||||
|
to = json['To'];
|
||||||
|
searchType = json['SearchType'];
|
||||||
|
mobileNo = json['MobileNo'];
|
||||||
|
identificationNo = json['IdentificationNo'];
|
||||||
|
editedBy = json['EditedBy'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
tokenID = json['TokenID'];
|
||||||
|
languageID = json['LanguageID'];
|
||||||
|
stamp = json['stamp'];
|
||||||
|
iPAdress = json['IPAdress'];
|
||||||
|
versionID = json['VersionID'];
|
||||||
|
channel = json['Channel'];
|
||||||
|
sessionID = json['SessionID'];
|
||||||
|
isLoginForDoctorApp = json['IsLoginForDoctorApp'];
|
||||||
|
patientOutSA = json['PatientOutSA'];
|
||||||
|
vidaAuthTokenID = json['VidaAuthTokenID'];
|
||||||
|
vidaRefreshTokenID = json['VidaRefreshTokenID'];
|
||||||
|
deviceTypeID = json['DeviceTypeID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['FirstName'] = this.firstName;
|
||||||
|
data['TemplateID'] = this.templateID;
|
||||||
|
data['MiddleName'] = this.middleName;
|
||||||
|
data['LastName'] = this.lastName;
|
||||||
|
data['PatientMobileNumber'] = this.patientMobileNumber;
|
||||||
|
data['PatientIdentificationID'] = this.patientIdentificationID;
|
||||||
|
data['PatientID'] = this.patientID;
|
||||||
|
data['From'] = this.from;
|
||||||
|
data['To'] = this.to;
|
||||||
|
data['SearchType'] = this.searchType;
|
||||||
|
data['MobileNo'] = this.mobileNo;
|
||||||
|
data['IdentificationNo'] = this.identificationNo;
|
||||||
|
data['EditedBy'] = this.editedBy;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['TokenID'] = this.tokenID;
|
||||||
|
data['LanguageID'] = this.languageID;
|
||||||
|
data['stamp'] = this.stamp;
|
||||||
|
data['IPAdress'] = this.iPAdress;
|
||||||
|
data['VersionID'] = this.versionID;
|
||||||
|
data['Channel'] = this.channel;
|
||||||
|
data['SessionID'] = this.sessionID;
|
||||||
|
data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
|
||||||
|
data['PatientOutSA'] = this.patientOutSA;
|
||||||
|
data['VidaAuthTokenID'] = this.vidaAuthTokenID;
|
||||||
|
data['VidaRefreshTokenID'] = this.vidaRefreshTokenID;
|
||||||
|
data['DeviceTypeID'] = this.deviceTypeID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
class MyReferralPatientRequestModel {
|
||||||
|
int channel;
|
||||||
|
int clinicID;
|
||||||
|
int doctorID;
|
||||||
|
int editedBy;
|
||||||
|
String firstName;
|
||||||
|
String from;
|
||||||
|
String iPAdress;
|
||||||
|
bool isLoginForDoctorApp;
|
||||||
|
int languageID;
|
||||||
|
String lastName;
|
||||||
|
String middleName;
|
||||||
|
int patientID;
|
||||||
|
String patientIdentificationID;
|
||||||
|
String patientMobileNumber;
|
||||||
|
bool patientOutSA;
|
||||||
|
int patientTypeID;
|
||||||
|
int projectID;
|
||||||
|
String sessionID;
|
||||||
|
String stamp;
|
||||||
|
String to;
|
||||||
|
String tokenID;
|
||||||
|
double versionID;
|
||||||
|
String vidaAuthTokenID;
|
||||||
|
|
||||||
|
MyReferralPatientRequestModel(
|
||||||
|
{this.channel,
|
||||||
|
this.clinicID,
|
||||||
|
this.doctorID,
|
||||||
|
this.editedBy,
|
||||||
|
this.firstName,
|
||||||
|
this.from,
|
||||||
|
this.iPAdress,
|
||||||
|
this.isLoginForDoctorApp,
|
||||||
|
this.languageID,
|
||||||
|
this.lastName,
|
||||||
|
this.middleName,
|
||||||
|
this.patientID,
|
||||||
|
this.patientIdentificationID,
|
||||||
|
this.patientMobileNumber,
|
||||||
|
this.patientOutSA,
|
||||||
|
this.patientTypeID,
|
||||||
|
this.projectID,
|
||||||
|
this.sessionID,
|
||||||
|
this.stamp,
|
||||||
|
this.to,
|
||||||
|
this.tokenID,
|
||||||
|
this.versionID,
|
||||||
|
this.vidaAuthTokenID});
|
||||||
|
|
||||||
|
MyReferralPatientRequestModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
channel = json['Channel'];
|
||||||
|
clinicID = json['ClinicID'];
|
||||||
|
doctorID = json['DoctorID'];
|
||||||
|
editedBy = json['EditedBy'];
|
||||||
|
firstName = json['FirstName'];
|
||||||
|
from = json['From'];
|
||||||
|
iPAdress = json['IPAdress'];
|
||||||
|
isLoginForDoctorApp = json['IsLoginForDoctorApp'];
|
||||||
|
languageID = json['LanguageID'];
|
||||||
|
lastName = json['LastName'];
|
||||||
|
middleName = json['MiddleName'];
|
||||||
|
patientID = json['PatientID'];
|
||||||
|
patientIdentificationID = json['PatientIdentificationID'];
|
||||||
|
patientMobileNumber = json['PatientMobileNumber'];
|
||||||
|
patientOutSA = json['PatientOutSA'];
|
||||||
|
patientTypeID = json['PatientTypeID'];
|
||||||
|
projectID = json['ProjectID'];
|
||||||
|
sessionID = json['SessionID'];
|
||||||
|
stamp = json['stamp'];
|
||||||
|
to = json['To'];
|
||||||
|
tokenID = json['TokenID'];
|
||||||
|
versionID = json['VersionID'];
|
||||||
|
vidaAuthTokenID = json['VidaAuthTokenID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['Channel'] = this.channel;
|
||||||
|
data['ClinicID'] = this.clinicID;
|
||||||
|
data['DoctorID'] = this.doctorID;
|
||||||
|
data['EditedBy'] = this.editedBy;
|
||||||
|
data['FirstName'] = this.firstName;
|
||||||
|
data['From'] = this.from;
|
||||||
|
data['IPAdress'] = this.iPAdress;
|
||||||
|
data['IsLoginForDoctorApp'] = this.isLoginForDoctorApp;
|
||||||
|
data['LanguageID'] = this.languageID;
|
||||||
|
data['LastName'] = this.lastName;
|
||||||
|
data['MiddleName'] = this.middleName;
|
||||||
|
data['PatientID'] = this.patientID;
|
||||||
|
data['PatientIdentificationID'] = this.patientIdentificationID;
|
||||||
|
data['PatientMobileNumber'] = this.patientMobileNumber;
|
||||||
|
data['PatientOutSA'] = this.patientOutSA;
|
||||||
|
data['PatientTypeID'] = this.patientTypeID;
|
||||||
|
data['ProjectID'] = this.projectID;
|
||||||
|
data['SessionID'] = this.sessionID;
|
||||||
|
data['stamp'] = this.stamp;
|
||||||
|
data['To'] = this.to;
|
||||||
|
data['TokenID'] = this.tokenID;
|
||||||
|
data['VersionID'] = this.versionID;
|
||||||
|
data['VidaAuthTokenID'] = this.vidaAuthTokenID;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||