;
+}
diff --git a/android/easypermissions/src/main/AndroidManifest.xml b/android/easypermissions/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..16a209f6
--- /dev/null
+++ b/android/easypermissions/src/main/AndroidManifest.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/AfterPermissionGranted.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AfterPermissionGranted.java
new file mode 100644
index 00000000..09202a22
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AfterPermissionGranted.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pub.devrel.easypermissions;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterPermissionGranted {
+
+ int value();
+
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialog.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialog.java
new file mode 100644
index 00000000..4407e4fc
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialog.java
@@ -0,0 +1,356 @@
+package pub.devrel.easypermissions;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.StringRes;
+import androidx.annotation.StyleRes;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+
+/**
+ * Dialog to prompt the user to go to the app's settings screen and enable permissions. If the user
+ * clicks 'OK' on the dialog, they are sent to the settings screen. The result is returned to the
+ * Activity via {@see Activity#onActivityResult(int, int, Intent)}.
+ *
+ * Use the {@link Builder} to create and display a dialog.
+ */
+public class AppSettingsDialog implements Parcelable {
+
+ private static final String TAG = "EasyPermissions";
+
+ public static final int DEFAULT_SETTINGS_REQ_CODE = 16061;
+
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
+ @Override
+ public AppSettingsDialog createFromParcel(Parcel in) {
+ return new AppSettingsDialog(in);
+ }
+
+ @Override
+ public AppSettingsDialog[] newArray(int size) {
+ return new AppSettingsDialog[size];
+ }
+ };
+
+ static final String EXTRA_APP_SETTINGS = "extra_app_settings";
+
+ @StyleRes
+ private final int mThemeResId;
+ private final String mRationale;
+ private final String mTitle;
+ private final String mPositiveButtonText;
+ private final String mNegativeButtonText;
+ private final int mRequestCode;
+ private final int mIntentFlags;
+
+ private Object mActivityOrFragment;
+ private Context mContext;
+
+ private AppSettingsDialog(Parcel in) {
+ mThemeResId = in.readInt();
+ mRationale = in.readString();
+ mTitle = in.readString();
+ mPositiveButtonText = in.readString();
+ mNegativeButtonText = in.readString();
+ mRequestCode = in.readInt();
+ mIntentFlags = in.readInt();
+ }
+
+ private AppSettingsDialog(@NonNull final Object activityOrFragment,
+ @StyleRes int themeResId,
+ @Nullable String rationale,
+ @Nullable String title,
+ @Nullable String positiveButtonText,
+ @Nullable String negativeButtonText,
+ int requestCode,
+ int intentFlags) {
+ setActivityOrFragment(activityOrFragment);
+ mThemeResId = themeResId;
+ mRationale = rationale;
+ mTitle = title;
+ mPositiveButtonText = positiveButtonText;
+ mNegativeButtonText = negativeButtonText;
+ mRequestCode = requestCode;
+ mIntentFlags = intentFlags;
+ }
+
+ static AppSettingsDialog fromIntent(Intent intent, Activity activity) {
+ AppSettingsDialog dialog = intent.getParcelableExtra(AppSettingsDialog.EXTRA_APP_SETTINGS);
+
+ // It's not clear how this could happen, but in the case that it does we should try
+ // to avoid a runtime crash and just use the default dialog.
+ // https://github.com/googlesamples/easypermissions/issues/278
+ if (dialog == null) {
+ Log.e(TAG, "Intent contains null value for EXTRA_APP_SETTINGS: "
+ + "intent=" + intent
+ + ", "
+ + "extras=" + intent.getExtras());
+
+ dialog = new AppSettingsDialog.Builder(activity).build();
+ }
+
+ dialog.setActivityOrFragment(activity);
+ return dialog;
+ }
+
+ private void setActivityOrFragment(Object activityOrFragment) {
+ mActivityOrFragment = activityOrFragment;
+
+ if (activityOrFragment instanceof Activity) {
+ mContext = (Activity) activityOrFragment;
+ } else if (activityOrFragment instanceof Fragment) {
+ mContext = ((Fragment) activityOrFragment).getContext();
+ } else {
+ throw new IllegalStateException("Unknown object: " + activityOrFragment);
+ }
+ }
+
+ private void startForResult(Intent intent) {
+ if (mActivityOrFragment instanceof Activity) {
+ ((Activity) mActivityOrFragment).startActivityForResult(intent, mRequestCode);
+ } else if (mActivityOrFragment instanceof Fragment) {
+ ((Fragment) mActivityOrFragment).startActivityForResult(intent, mRequestCode);
+ }
+ }
+
+ /**
+ * Display the built dialog.
+ */
+ public void show() {
+ startForResult(AppSettingsDialogHolderActivity.createShowDialogIntent(mContext, this));
+ }
+
+ /**
+ * Show the dialog. {@link #show()} is a wrapper to ensure backwards compatibility
+ */
+ AlertDialog showDialog(DialogInterface.OnClickListener positiveListener,
+ DialogInterface.OnClickListener negativeListener) {
+ AlertDialog.Builder builder;
+ if (mThemeResId != -1) {
+ builder = new AlertDialog.Builder(mContext, mThemeResId);
+ } else {
+ builder = new AlertDialog.Builder(mContext);
+ }
+ return builder
+ .setCancelable(false)
+ .setTitle(mTitle)
+ .setMessage(mRationale)
+ .setPositiveButton(mPositiveButtonText, positiveListener)
+ .setNegativeButton(mNegativeButtonText, negativeListener)
+ .show();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mThemeResId);
+ dest.writeString(mRationale);
+ dest.writeString(mTitle);
+ dest.writeString(mPositiveButtonText);
+ dest.writeString(mNegativeButtonText);
+ dest.writeInt(mRequestCode);
+ dest.writeInt(mIntentFlags);
+ }
+
+ int getIntentFlags() {
+ return mIntentFlags;
+ }
+
+ /**
+ * Builder for an {@link AppSettingsDialog}.
+ */
+ public static class Builder {
+
+ private final Object mActivityOrFragment;
+ private final Context mContext;
+ @StyleRes
+ private int mThemeResId = -1;
+ private String mRationale;
+ private String mTitle;
+ private String mPositiveButtonText;
+ private String mNegativeButtonText;
+ private int mRequestCode = -1;
+ private boolean mOpenInNewTask = false;
+
+ /**
+ * Create a new Builder for an {@link AppSettingsDialog}.
+ *
+ * @param activity the {@link Activity} in which to display the dialog.
+ */
+ public Builder(@NonNull Activity activity) {
+ mActivityOrFragment = activity;
+ mContext = activity;
+ }
+
+ /**
+ * Create a new Builder for an {@link AppSettingsDialog}.
+ *
+ * @param fragment the {@link Fragment} in which to display the dialog.
+ */
+ public Builder(@NonNull Fragment fragment) {
+ mActivityOrFragment = fragment;
+ mContext = fragment.getContext();
+ }
+
+ /**
+ * Set the dialog theme.
+ */
+ @NonNull
+ public Builder setThemeResId(@StyleRes int themeResId) {
+ mThemeResId = themeResId;
+ return this;
+ }
+
+ /**
+ * Set the title dialog. Default is "Permissions Required".
+ */
+ @NonNull
+ public Builder setTitle(@Nullable String title) {
+ mTitle = title;
+ return this;
+ }
+
+ /**
+ * Set the title dialog. Default is "Permissions Required".
+ */
+ @NonNull
+ public Builder setTitle(@StringRes int title) {
+ mTitle = mContext.getString(title);
+ return this;
+ }
+
+ /**
+ * Set the rationale dialog. Default is
+ * "This app may not work correctly without the requested permissions.
+ * Open the app settings screen to modify app permissions."
+ */
+ @NonNull
+ public Builder setRationale(@Nullable String rationale) {
+ mRationale = rationale;
+ return this;
+ }
+
+ /**
+ * Set the rationale dialog. Default is
+ * "This app may not work correctly without the requested permissions.
+ * Open the app settings screen to modify app permissions."
+ */
+ @NonNull
+ public Builder setRationale(@StringRes int rationale) {
+ mRationale = mContext.getString(rationale);
+ return this;
+ }
+
+ /**
+ * Set the positive button text, default is {@link android.R.string#ok}.
+ */
+ @NonNull
+ public Builder setPositiveButton(@Nullable String text) {
+ mPositiveButtonText = text;
+ return this;
+ }
+
+ /**
+ * Set the positive button text, default is {@link android.R.string#ok}.
+ */
+ @NonNull
+ public Builder setPositiveButton(@StringRes int textId) {
+ mPositiveButtonText = mContext.getString(textId);
+ return this;
+ }
+
+ /**
+ * Set the negative button text, default is {@link android.R.string#cancel}.
+ *
+ * To know if a user cancelled the request, check if your permissions were given with {@link
+ * EasyPermissions#hasPermissions(Context, String...)} in {@see
+ * Activity#onActivityResult(int, int, Intent)}. If you still don't have the right
+ * permissions, then the request was cancelled.
+ */
+ @NonNull
+ public Builder setNegativeButton(@Nullable String text) {
+ mNegativeButtonText = text;
+ return this;
+ }
+
+ /**
+ * Set the negative button text, default is {@link android.R.string#cancel}.
+ */
+ @NonNull
+ public Builder setNegativeButton(@StringRes int textId) {
+ mNegativeButtonText = mContext.getString(textId);
+ return this;
+ }
+
+ /**
+ * Set the request code use when launching the Settings screen for result, can be retrieved
+ * in the calling Activity's {@see Activity#onActivityResult(int, int, Intent)} method.
+ * Default is {@link #DEFAULT_SETTINGS_REQ_CODE}.
+ */
+ @NonNull
+ public Builder setRequestCode(int requestCode) {
+ mRequestCode = requestCode;
+ return this;
+ }
+
+ /**
+ * Set whether the settings screen should be opened in a separate task. This is achieved by
+ * setting {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK#FLAG_ACTIVITY_NEW_TASK} on
+ * the Intent used to open the settings screen.
+ */
+ @NonNull
+ public Builder setOpenInNewTask(boolean openInNewTask) {
+ mOpenInNewTask = openInNewTask;
+ return this;
+ }
+
+ /**
+ * Build the {@link AppSettingsDialog} from the specified options. Generally followed by a
+ * call to {@link AppSettingsDialog#show()}.
+ */
+ @NonNull
+ public AppSettingsDialog build() {
+ mRationale = TextUtils.isEmpty(mRationale) ?
+ mContext.getString(R.string.rationale_ask_again) : mRationale;
+ mTitle = TextUtils.isEmpty(mTitle) ?
+ mContext.getString(R.string.title_settings_dialog) : mTitle;
+ mPositiveButtonText = TextUtils.isEmpty(mPositiveButtonText) ?
+ mContext.getString(android.R.string.ok) : mPositiveButtonText;
+ mNegativeButtonText = TextUtils.isEmpty(mNegativeButtonText) ?
+ mContext.getString(android.R.string.cancel) : mNegativeButtonText;
+ mRequestCode = mRequestCode > 0 ? mRequestCode : DEFAULT_SETTINGS_REQ_CODE;
+
+ int intentFlags = 0;
+ if (mOpenInNewTask) {
+ intentFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
+ }
+
+ return new AppSettingsDialog(
+ mActivityOrFragment,
+ mThemeResId,
+ mRationale,
+ mTitle,
+ mPositiveButtonText,
+ mNegativeButtonText,
+ mRequestCode,
+ intentFlags);
+ }
+
+ }
+
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialogHolderActivity.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialogHolderActivity.java
new file mode 100644
index 00000000..d996dd7f
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/AppSettingsDialogHolderActivity.java
@@ -0,0 +1,65 @@
+package pub.devrel.easypermissions;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import androidx.annotation.RestrictTo;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class AppSettingsDialogHolderActivity extends AppCompatActivity implements DialogInterface.OnClickListener {
+ private static final int APP_SETTINGS_RC = 7534;
+
+ private AlertDialog mDialog;
+ private int mIntentFlags;
+
+ public static Intent createShowDialogIntent(Context context, AppSettingsDialog dialog) {
+ Intent intent = new Intent(context, AppSettingsDialogHolderActivity.class);
+ intent.putExtra(AppSettingsDialog.EXTRA_APP_SETTINGS, dialog);
+ return intent;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ AppSettingsDialog appSettingsDialog = AppSettingsDialog.fromIntent(getIntent(), this);
+ mIntentFlags = appSettingsDialog.getIntentFlags();
+ mDialog = appSettingsDialog.showDialog(this, this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mDialog != null && mDialog.isShowing()) {
+ mDialog.dismiss();
+ }
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == Dialog.BUTTON_POSITIVE) {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+ .setData(Uri.fromParts("package", getPackageName(), null));
+ intent.addFlags(mIntentFlags);
+ startActivityForResult(intent, APP_SETTINGS_RC);
+ } else if (which == Dialog.BUTTON_NEGATIVE) {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ } else {
+ throw new IllegalStateException("Unknown button type: " + which);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ setResult(resultCode, data);
+ finish();
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/EasyPermissions.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/EasyPermissions.java
new file mode 100644
index 00000000..dfc20d0e
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/EasyPermissions.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package pub.devrel.easypermissions;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import androidx.annotation.IntRange;
+import androidx.annotation.NonNull;
+import androidx.annotation.Size;
+import androidx.core.app.ActivityCompat;
+import androidx.fragment.app.Fragment;
+import androidx.core.content.ContextCompat;
+import android.util.Log;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import pub.devrel.easypermissions.helper.PermissionHelper;
+
+/**
+ * Utility to request and check System permissions for apps targeting Android M (API >= 23).
+ */
+public class EasyPermissions {
+
+ /**
+ * Callback interface to receive the results of {@code EasyPermissions.requestPermissions()}
+ * calls.
+ */
+ public interface PermissionCallbacks extends ActivityCompat.OnRequestPermissionsResultCallback {
+
+ void onPermissionsGranted(int requestCode, @NonNull List perms);
+
+ void onPermissionsDenied(int requestCode, @NonNull List perms);
+ }
+
+ /**
+ * Callback interface to receive button clicked events of the rationale dialog
+ */
+ public interface RationaleCallbacks {
+ void onRationaleAccepted(int requestCode);
+
+ void onRationaleDenied(int requestCode);
+ }
+
+ private static final String TAG = "EasyPermissions";
+
+ /**
+ * Check if the calling context has a set of permissions.
+ *
+ * @param context the calling context.
+ * @param perms one ore more permissions, such as {@link Manifest.permission#CAMERA}.
+ * @return true if all permissions are already granted, false if at least one permission is not
+ * yet granted.
+ * @see Manifest.permission
+ */
+ public static boolean hasPermissions(@NonNull Context context,
+ @Size(min = 1) @NonNull String... perms) {
+ // Always return true for SDK < M, let the system deal with the permissions
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ Log.w(TAG, "hasPermissions: API version < M, returning true by default");
+
+ // DANGER ZONE!!! Changing this will break the library.
+ return true;
+ }
+
+ // Null context may be passed if we have detected Low API (less than M) so getting
+ // to this point with a null context should not be possible.
+ if (context == null) {
+ throw new IllegalArgumentException("Can't check permissions for null context");
+ }
+
+ for (String perm : perms) {
+ if (ContextCompat.checkSelfPermission(context, perm)
+ != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Request a set of permissions, showing a rationale if the system requests it.
+ *
+ * @param host requesting context.
+ * @param rationale a message explaining why the application needs this set of permissions;
+ * will be displayed if the user rejects the request the first time.
+ * @param requestCode request code to track this request, must be < 256.
+ * @param perms a set of permissions to be requested.
+ * @see Manifest.permission
+ */
+ public static void requestPermissions(
+ @NonNull Activity host, @NonNull String rationale,
+ @IntRange(from = 0, to = 255) int requestCode, @Size(min = 1) @NonNull String... perms) {
+ requestPermissions(
+ new PermissionRequest.Builder(host, requestCode, perms)
+ .setRationale(rationale)
+ .build());
+ }
+
+ /**
+ * Request permissions from a Support Fragment with standard OK/Cancel buttons.
+ *
+ * @see #requestPermissions(Activity, String, int, String...)
+ */
+ public static void requestPermissions(
+ @NonNull Fragment host, @NonNull String rationale,
+ @IntRange(from = 0, to = 255) int requestCode, @Size(min = 1) @NonNull String... perms) {
+ requestPermissions(
+ new PermissionRequest.Builder(host, requestCode, perms)
+ .setRationale(rationale)
+ .build());
+ }
+
+ /**
+ * Request a set of permissions.
+ *
+ * @param request the permission request
+ * @see PermissionRequest
+ */
+ public static void requestPermissions(PermissionRequest request) {
+
+ // Check for permissions before dispatching the request
+ if (hasPermissions(request.getHelper().getContext(), request.getPerms())) {
+ notifyAlreadyHasPermissions(
+ request.getHelper().getHost(), request.getRequestCode(), request.getPerms());
+ return;
+ }
+
+ // Request permissions
+ request.getHelper().requestPermissions(
+ request.getRationale(),
+ request.getPositiveButtonText(),
+ request.getNegativeButtonText(),
+ request.getTheme(),
+ request.getRequestCode(),
+ request.getPerms());
+ }
+
+ /**
+ * Handle the result of a permission request, should be called from the calling {@link
+ * Activity}'s {@link ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(int,
+ * String[], int[])} method.
+ *
+ * If any permissions were granted or denied, the {@code object} will receive the appropriate
+ * callbacks through {@link PermissionCallbacks} and methods annotated with {@link
+ * AfterPermissionGranted} will be run if appropriate.
+ *
+ * @param requestCode requestCode argument to permission result callback.
+ * @param permissions permissions argument to permission result callback.
+ * @param grantResults grantResults argument to permission result callback.
+ * @param receivers an array of objects that have a method annotated with {@link
+ * AfterPermissionGranted} or implement {@link PermissionCallbacks}.
+ */
+ public static void onRequestPermissionsResult(@IntRange(from = 0, to = 255) int requestCode,
+ @NonNull String[] permissions,
+ @NonNull int[] grantResults,
+ @NonNull Object... receivers) {
+ // Make a collection of granted and denied permissions from the request.
+ List granted = new ArrayList<>();
+ List denied = new ArrayList<>();
+ for (int i = 0; i < permissions.length; i++) {
+ String perm = permissions[i];
+ if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
+ granted.add(perm);
+ } else {
+ denied.add(perm);
+ }
+ }
+
+ // iterate through all receivers
+ for (Object object : receivers) {
+ // Report granted permissions, if any.
+ if (!granted.isEmpty()) {
+ if (object instanceof PermissionCallbacks) {
+ ((PermissionCallbacks) object).onPermissionsGranted(requestCode, granted);
+ }
+ }
+
+ // Report denied permissions, if any.
+ if (!denied.isEmpty()) {
+ if (object instanceof PermissionCallbacks) {
+ ((PermissionCallbacks) object).onPermissionsDenied(requestCode, denied);
+ }
+ }
+
+ // If 100% successful, call annotated methods
+ if (!granted.isEmpty() && denied.isEmpty()) {
+ runAnnotatedMethods(object, requestCode);
+ }
+ }
+ }
+
+ /**
+ * Check if at least one permission in the list of denied permissions has been permanently
+ * denied (user clicked "Never ask again").
+ *
+ * Note : Due to a limitation in the information provided by the Android
+ * framework permissions API, this method only works after the permission
+ * has been denied and your app has received the onPermissionsDenied callback.
+ * Otherwise the library cannot distinguish permanent denial from the
+ * "not yet denied" case.
+ *
+ * @param host context requesting permissions.
+ * @param deniedPermissions list of denied permissions, usually from {@link
+ * PermissionCallbacks#onPermissionsDenied(int, List)}
+ * @return {@code true} if at least one permission in the list was permanently denied.
+ */
+ public static boolean somePermissionPermanentlyDenied(@NonNull Activity host,
+ @NonNull List deniedPermissions) {
+ return PermissionHelper.newInstance(host)
+ .somePermissionPermanentlyDenied(deniedPermissions);
+ }
+
+ /**
+ * @see #somePermissionPermanentlyDenied(Activity, List)
+ */
+ public static boolean somePermissionPermanentlyDenied(@NonNull Fragment host,
+ @NonNull List deniedPermissions) {
+ return PermissionHelper.newInstance(host)
+ .somePermissionPermanentlyDenied(deniedPermissions);
+ }
+
+ /**
+ * Check if a permission has been permanently denied (user clicked "Never ask again").
+ *
+ * @param host context requesting permissions.
+ * @param deniedPermission denied permission.
+ * @return {@code true} if the permissions has been permanently denied.
+ */
+ public static boolean permissionPermanentlyDenied(@NonNull Activity host,
+ @NonNull String deniedPermission) {
+ return PermissionHelper.newInstance(host).permissionPermanentlyDenied(deniedPermission);
+ }
+
+ /**
+ * @see #permissionPermanentlyDenied(Activity, String)
+ */
+ public static boolean permissionPermanentlyDenied(@NonNull Fragment host,
+ @NonNull String deniedPermission) {
+ return PermissionHelper.newInstance(host).permissionPermanentlyDenied(deniedPermission);
+ }
+
+ /**
+ * See if some denied permission has been permanently denied.
+ *
+ * @param host requesting context.
+ * @param perms array of permissions.
+ * @return true if the user has previously denied any of the {@code perms} and we should show a
+ * rationale, false otherwise.
+ */
+ public static boolean somePermissionDenied(@NonNull Activity host,
+ @NonNull String... perms) {
+ return PermissionHelper.newInstance(host).somePermissionDenied(perms);
+ }
+
+ /**
+ * @see #somePermissionDenied(Activity, String...)
+ */
+ public static boolean somePermissionDenied(@NonNull Fragment host,
+ @NonNull String... perms) {
+ return PermissionHelper.newInstance(host).somePermissionDenied(perms);
+ }
+
+ /**
+ * Run permission callbacks on an object that requested permissions but already has them by
+ * simulating {@link PackageManager#PERMISSION_GRANTED}.
+ *
+ * @param object the object requesting permissions.
+ * @param requestCode the permission request code.
+ * @param perms a list of permissions requested.
+ */
+ private static void notifyAlreadyHasPermissions(@NonNull Object object,
+ int requestCode,
+ @NonNull String[] perms) {
+ int[] grantResults = new int[perms.length];
+ for (int i = 0; i < perms.length; i++) {
+ grantResults[i] = PackageManager.PERMISSION_GRANTED;
+ }
+
+ onRequestPermissionsResult(requestCode, perms, grantResults, object);
+ }
+
+ /**
+ * Find all methods annotated with {@link AfterPermissionGranted} on a given object with the
+ * correct requestCode argument.
+ *
+ * @param object the object with annotated methods.
+ * @param requestCode the requestCode passed to the annotation.
+ */
+ private static void runAnnotatedMethods(@NonNull Object object, int requestCode) {
+ Class clazz = object.getClass();
+ if (isUsingAndroidAnnotations(object)) {
+ clazz = clazz.getSuperclass();
+ }
+
+ while (clazz != null) {
+ for (Method method : clazz.getDeclaredMethods()) {
+ AfterPermissionGranted ann = method.getAnnotation(AfterPermissionGranted.class);
+ if (ann != null) {
+ // Check for annotated methods with matching request code.
+ if (ann.value() == requestCode) {
+ // Method must be void so that we can invoke it
+ if (method.getParameterTypes().length > 0) {
+ throw new RuntimeException(
+ "Cannot execute method " + method.getName() + " because it is non-void method and/or has input parameters.");
+ }
+
+ try {
+ // Make method accessible if private
+ if (!method.isAccessible()) {
+ method.setAccessible(true);
+ }
+ method.invoke(object);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "runDefaultMethod:IllegalAccessException", e);
+ } catch (InvocationTargetException e) {
+ Log.e(TAG, "runDefaultMethod:InvocationTargetException", e);
+ }
+ }
+ }
+ }
+
+ clazz = clazz.getSuperclass();
+ }
+ }
+
+ /**
+ * Determine if the project is using the AndroidAnnotations library.
+ */
+ private static boolean isUsingAndroidAnnotations(@NonNull Object object) {
+ if (!object.getClass().getSimpleName().endsWith("_")) {
+ return false;
+ }
+ try {
+ Class clazz = Class.forName("org.androidannotations.api.view.HasViews");
+ return clazz.isInstance(object);
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/PermissionRequest.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/PermissionRequest.java
new file mode 100644
index 00000000..02d2e6d1
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/PermissionRequest.java
@@ -0,0 +1,260 @@
+package pub.devrel.easypermissions;
+
+import android.app.Activity;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.Size;
+import androidx.annotation.StringRes;
+import androidx.annotation.StyleRes;
+import androidx.fragment.app.Fragment;
+
+import java.util.Arrays;
+
+import pub.devrel.easypermissions.helper.PermissionHelper;
+
+/**
+ * An immutable model object that holds all of the parameters associated with a permission request,
+ * such as the permissions, request code, and rationale.
+ *
+ * @see EasyPermissions#requestPermissions(PermissionRequest)
+ * @see PermissionRequest.Builder
+ */
+public final class PermissionRequest {
+ private final PermissionHelper mHelper;
+ private final String[] mPerms;
+ private final int mRequestCode;
+ private final String mRationale;
+ private final String mPositiveButtonText;
+ private final String mNegativeButtonText;
+ private final int mTheme;
+
+ private PermissionRequest(PermissionHelper helper,
+ String[] perms,
+ int requestCode,
+ String rationale,
+ String positiveButtonText,
+ String negativeButtonText,
+ int theme) {
+ mHelper = helper;
+ mPerms = perms.clone();
+ mRequestCode = requestCode;
+ mRationale = rationale;
+ mPositiveButtonText = positiveButtonText;
+ mNegativeButtonText = negativeButtonText;
+ mTheme = theme;
+ }
+
+ @NonNull
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ public PermissionHelper getHelper() {
+ return mHelper;
+ }
+
+ @NonNull
+ public String[] getPerms() {
+ return mPerms.clone();
+ }
+
+ public int getRequestCode() {
+ return mRequestCode;
+ }
+
+ @NonNull
+ public String getRationale() {
+ return mRationale;
+ }
+
+ @NonNull
+ public String getPositiveButtonText() {
+ return mPositiveButtonText;
+ }
+
+ @NonNull
+ public String getNegativeButtonText() {
+ return mNegativeButtonText;
+ }
+
+ @StyleRes
+ public int getTheme() {
+ return mTheme;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ PermissionRequest request = (PermissionRequest) o;
+
+ return Arrays.equals(mPerms, request.mPerms) && mRequestCode == request.mRequestCode;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Arrays.hashCode(mPerms);
+ result = 31 * result + mRequestCode;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "PermissionRequest{" +
+ "mHelper=" + mHelper +
+ ", mPerms=" + Arrays.toString(mPerms) +
+ ", mRequestCode=" + mRequestCode +
+ ", mRationale='" + mRationale + '\'' +
+ ", mPositiveButtonText='" + mPositiveButtonText + '\'' +
+ ", mNegativeButtonText='" + mNegativeButtonText + '\'' +
+ ", mTheme=" + mTheme +
+ '}';
+ }
+
+ /**
+ * Builder to build a permission request with variable options.
+ *
+ * @see PermissionRequest
+ */
+ public static final class Builder {
+ private final PermissionHelper mHelper;
+ private final int mRequestCode;
+ private final String[] mPerms;
+
+ private String mRationale;
+ private String mPositiveButtonText;
+ private String mNegativeButtonText;
+ private int mTheme = -1;
+
+ /**
+ * Construct a new permission request builder with a host, request code, and the requested
+ * permissions.
+ *
+ * @param activity the permission request host
+ * @param requestCode request code to track this request; must be < 256
+ * @param perms the set of permissions to be requested
+ */
+ public Builder(@NonNull Activity activity, int requestCode,
+ @NonNull @Size(min = 1) String... perms) {
+ mHelper = PermissionHelper.newInstance(activity);
+ mRequestCode = requestCode;
+ mPerms = perms;
+ }
+
+ /**
+ * @see #Builder(Activity, int, String...)
+ */
+ public Builder(@NonNull Fragment fragment, int requestCode,
+ @NonNull @Size(min = 1) String... perms) {
+ mHelper = PermissionHelper.newInstance(fragment);
+ mRequestCode = requestCode;
+ mPerms = perms;
+ }
+
+ /**
+ * Set the rationale to display to the user if they don't allow your permissions on the
+ * first try. This rationale will be shown as long as the user has denied your permissions
+ * at least once, but has not yet permanently denied your permissions. Should the user
+ * permanently deny your permissions, use the {@link AppSettingsDialog} instead.
+ *
+ * The default rationale text is {@link R.string#rationale_ask}.
+ *
+ * @param rationale the rationale to be displayed to the user should they deny your
+ * permission at least once
+ */
+ @NonNull
+ public Builder setRationale(@Nullable String rationale) {
+ mRationale = rationale;
+ return this;
+ }
+
+ /**
+ * @param resId the string resource to be used as a rationale
+ * @see #setRationale(String)
+ */
+ @NonNull
+ public Builder setRationale(@StringRes int resId) {
+ mRationale = mHelper.getContext().getString(resId);
+ return this;
+ }
+
+ /**
+ * Set the positive button text for the rationale dialog should it be shown.
+ *
+ * The default is {@link android.R.string#ok}
+ */
+ @NonNull
+ public Builder setPositiveButtonText(@Nullable String positiveButtonText) {
+ mPositiveButtonText = positiveButtonText;
+ return this;
+ }
+
+ /**
+ * @see #setPositiveButtonText(String)
+ */
+ @NonNull
+ public Builder setPositiveButtonText(@StringRes int resId) {
+ mPositiveButtonText = mHelper.getContext().getString(resId);
+ return this;
+ }
+
+ /**
+ * Set the negative button text for the rationale dialog should it be shown.
+ *
+ * The default is {@link android.R.string#cancel}
+ */
+ @NonNull
+ public Builder setNegativeButtonText(@Nullable String negativeButtonText) {
+ mNegativeButtonText = negativeButtonText;
+ return this;
+ }
+
+ /**
+ * @see #setNegativeButtonText(String)
+ */
+ @NonNull
+ public Builder setNegativeButtonText(@StringRes int resId) {
+ mNegativeButtonText = mHelper.getContext().getString(resId);
+ return this;
+ }
+
+ /**
+ * Set the theme to be used for the rationale dialog should it be shown.
+ *
+ * @param theme a style resource
+ */
+ @NonNull
+ public Builder setTheme(@StyleRes int theme) {
+ mTheme = theme;
+ return this;
+ }
+
+ /**
+ * Build the permission request.
+ *
+ * @return the permission request
+ * @see EasyPermissions#requestPermissions(PermissionRequest)
+ * @see PermissionRequest
+ */
+ @NonNull
+ public PermissionRequest build() {
+ if (mRationale == null) {
+ mRationale = mHelper.getContext().getString(R.string.rationale_ask);
+ }
+ if (mPositiveButtonText == null) {
+ mPositiveButtonText = mHelper.getContext().getString(android.R.string.ok);
+ }
+ if (mNegativeButtonText == null) {
+ mNegativeButtonText = mHelper.getContext().getString(android.R.string.cancel);
+ }
+
+ return new PermissionRequest(
+ mHelper,
+ mPerms,
+ mRequestCode,
+ mRationale,
+ mPositiveButtonText,
+ mNegativeButtonText,
+ mTheme);
+ }
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogClickListener.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogClickListener.java
new file mode 100644
index 00000000..d07afffa
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogClickListener.java
@@ -0,0 +1,77 @@
+package pub.devrel.easypermissions;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import androidx.fragment.app.Fragment;
+
+import java.util.Arrays;
+
+import pub.devrel.easypermissions.helper.PermissionHelper;
+
+/**
+ * Click listener for either {@link RationaleDialogFragment} or {@link RationaleDialogFragmentCompat}.
+ */
+class RationaleDialogClickListener implements Dialog.OnClickListener {
+
+ private Object mHost;
+ private RationaleDialogConfig mConfig;
+ private EasyPermissions.PermissionCallbacks mCallbacks;
+ private EasyPermissions.RationaleCallbacks mRationaleCallbacks;
+
+ RationaleDialogClickListener(RationaleDialogFragmentCompat compatDialogFragment,
+ RationaleDialogConfig config,
+ EasyPermissions.PermissionCallbacks callbacks,
+ EasyPermissions.RationaleCallbacks rationaleCallbacks) {
+
+ mHost = compatDialogFragment.getParentFragment() != null
+ ? compatDialogFragment.getParentFragment()
+ : compatDialogFragment.getActivity();
+
+ mConfig = config;
+ mCallbacks = callbacks;
+ mRationaleCallbacks = rationaleCallbacks;
+
+ }
+
+ RationaleDialogClickListener(RationaleDialogFragment dialogFragment,
+ RationaleDialogConfig config,
+ EasyPermissions.PermissionCallbacks callbacks,
+ EasyPermissions.RationaleCallbacks dialogCallback) {
+
+ mHost = dialogFragment.getActivity();
+
+ mConfig = config;
+ mCallbacks = callbacks;
+ mRationaleCallbacks = dialogCallback;
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ int requestCode = mConfig.requestCode;
+ if (which == Dialog.BUTTON_POSITIVE) {
+ String[] permissions = mConfig.permissions;
+ if (mRationaleCallbacks != null) {
+ mRationaleCallbacks.onRationaleAccepted(requestCode);
+ }
+ if (mHost instanceof Fragment) {
+ PermissionHelper.newInstance((Fragment) mHost).directRequestPermissions(requestCode, permissions);
+ } else if (mHost instanceof Activity) {
+ PermissionHelper.newInstance((Activity) mHost).directRequestPermissions(requestCode, permissions);
+ } else {
+ throw new RuntimeException("Host must be an Activity or Fragment!");
+ }
+ } else {
+ if (mRationaleCallbacks != null) {
+ mRationaleCallbacks.onRationaleDenied(requestCode);
+ }
+ notifyPermissionDenied();
+ }
+ }
+
+ private void notifyPermissionDenied() {
+ if (mCallbacks != null) {
+ mCallbacks.onPermissionsDenied(mConfig.requestCode, Arrays.asList(mConfig.permissions));
+ }
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogConfig.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogConfig.java
new file mode 100644
index 00000000..c64999c6
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogConfig.java
@@ -0,0 +1,95 @@
+package pub.devrel.easypermissions;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.StyleRes;
+import androidx.appcompat.app.AlertDialog;
+
+/**
+ * Configuration for either {@link RationaleDialogFragment} or {@link RationaleDialogFragmentCompat}.
+ */
+class RationaleDialogConfig {
+
+ private static final String KEY_POSITIVE_BUTTON = "positiveButton";
+ private static final String KEY_NEGATIVE_BUTTON = "negativeButton";
+ private static final String KEY_RATIONALE_MESSAGE = "rationaleMsg";
+ private static final String KEY_THEME = "theme";
+ private static final String KEY_REQUEST_CODE = "requestCode";
+ private static final String KEY_PERMISSIONS = "permissions";
+
+ String positiveButton;
+ String negativeButton;
+ int theme;
+ int requestCode;
+ String rationaleMsg;
+ String[] permissions;
+
+ RationaleDialogConfig(@NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @NonNull String rationaleMsg,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String[] permissions) {
+
+ this.positiveButton = positiveButton;
+ this.negativeButton = negativeButton;
+ this.rationaleMsg = rationaleMsg;
+ this.theme = theme;
+ this.requestCode = requestCode;
+ this.permissions = permissions;
+ }
+
+ RationaleDialogConfig(Bundle bundle) {
+ positiveButton = bundle.getString(KEY_POSITIVE_BUTTON);
+ negativeButton = bundle.getString(KEY_NEGATIVE_BUTTON);
+ rationaleMsg = bundle.getString(KEY_RATIONALE_MESSAGE);
+ theme = bundle.getInt(KEY_THEME);
+ requestCode = bundle.getInt(KEY_REQUEST_CODE);
+ permissions = bundle.getStringArray(KEY_PERMISSIONS);
+ }
+
+ Bundle toBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(KEY_POSITIVE_BUTTON, positiveButton);
+ bundle.putString(KEY_NEGATIVE_BUTTON, negativeButton);
+ bundle.putString(KEY_RATIONALE_MESSAGE, rationaleMsg);
+ bundle.putInt(KEY_THEME, theme);
+ bundle.putInt(KEY_REQUEST_CODE, requestCode);
+ bundle.putStringArray(KEY_PERMISSIONS, permissions);
+
+ return bundle;
+ }
+
+ AlertDialog createSupportDialog(Context context, Dialog.OnClickListener listener) {
+ AlertDialog.Builder builder;
+ if (theme > 0) {
+ builder = new AlertDialog.Builder(context, theme);
+ } else {
+ builder = new AlertDialog.Builder(context);
+ }
+ return builder
+ .setCancelable(false)
+ .setPositiveButton(positiveButton, listener)
+ .setNegativeButton(negativeButton, listener)
+ .setMessage(rationaleMsg)
+ .create();
+ }
+
+ android.app.AlertDialog createFrameworkDialog(Context context, Dialog.OnClickListener listener) {
+ android.app.AlertDialog.Builder builder;
+ if (theme > 0) {
+ builder = new android.app.AlertDialog.Builder(context, theme);
+ } else {
+ builder = new android.app.AlertDialog.Builder(context);
+ }
+ return builder
+ .setCancelable(false)
+ .setPositiveButton(positiveButton, listener)
+ .setNegativeButton(negativeButton, listener)
+ .setMessage(rationaleMsg)
+ .create();
+ }
+
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragment.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragment.java
new file mode 100644
index 00000000..c055a4f7
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragment.java
@@ -0,0 +1,113 @@
+package pub.devrel.easypermissions;
+
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.StyleRes;
+
+/**
+ * {@link DialogFragment} to display rationale for permission requests when the request comes from
+ * a Fragment or Activity that can host a Fragment.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class RationaleDialogFragment extends DialogFragment {
+
+ public static final String TAG = "RationaleDialogFragment";
+
+ private EasyPermissions.PermissionCallbacks mPermissionCallbacks;
+ private EasyPermissions.RationaleCallbacks mRationaleCallbacks;
+ private boolean mStateSaved = false;
+
+ public static RationaleDialogFragment newInstance(
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @NonNull String rationaleMsg,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String[] permissions) {
+
+ // Create new Fragment
+ RationaleDialogFragment dialogFragment = new RationaleDialogFragment();
+
+ // Initialize configuration as arguments
+ RationaleDialogConfig config = new RationaleDialogConfig(
+ positiveButton, negativeButton, rationaleMsg, theme, requestCode, permissions);
+ dialogFragment.setArguments(config.toBundle());
+
+ return dialogFragment;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && getParentFragment() != null) {
+ if (getParentFragment() instanceof EasyPermissions.PermissionCallbacks) {
+ mPermissionCallbacks = (EasyPermissions.PermissionCallbacks) getParentFragment();
+ }
+ if (getParentFragment() instanceof EasyPermissions.RationaleCallbacks){
+ mRationaleCallbacks = (EasyPermissions.RationaleCallbacks) getParentFragment();
+ }
+
+ }
+
+ if (context instanceof EasyPermissions.PermissionCallbacks) {
+ mPermissionCallbacks = (EasyPermissions.PermissionCallbacks) context;
+ }
+
+ if (context instanceof EasyPermissions.RationaleCallbacks) {
+ mRationaleCallbacks = (EasyPermissions.RationaleCallbacks) context;
+ }
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ mStateSaved = true;
+ super.onSaveInstanceState(outState);
+ }
+
+ /**
+ * Version of {@link #show(FragmentManager, String)} that no-ops when an IllegalStateException
+ * would otherwise occur.
+ */
+ public void showAllowingStateLoss(FragmentManager manager, String tag) {
+ // API 26 added this convenient method
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (manager.isStateSaved()) {
+ return;
+ }
+ }
+
+ if (mStateSaved) {
+ return;
+ }
+
+ show(manager, tag);
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mPermissionCallbacks = null;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Rationale dialog should not be cancelable
+ setCancelable(false);
+
+ // Get config from arguments, create click listener
+ RationaleDialogConfig config = new RationaleDialogConfig(getArguments());
+ RationaleDialogClickListener clickListener =
+ new RationaleDialogClickListener(this, config, mPermissionCallbacks, mRationaleCallbacks);
+
+ // Create an AlertDialog
+ return config.createFrameworkDialog(getActivity(), clickListener);
+ }
+
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragmentCompat.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragmentCompat.java
new file mode 100644
index 00000000..5a9306f4
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/RationaleDialogFragmentCompat.java
@@ -0,0 +1,97 @@
+package pub.devrel.easypermissions;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.StyleRes;
+import androidx.fragment.app.FragmentManager;
+import androidx.appcompat.app.AppCompatDialogFragment;
+
+/**
+ * {@link AppCompatDialogFragment} to display rationale for permission requests when the request
+ * comes from a Fragment or Activity that can host a Fragment.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class RationaleDialogFragmentCompat extends AppCompatDialogFragment {
+
+ public static final String TAG = "RationaleDialogFragmentCompat";
+
+ private EasyPermissions.PermissionCallbacks mPermissionCallbacks;
+ private EasyPermissions.RationaleCallbacks mRationaleCallbacks;
+
+ public static RationaleDialogFragmentCompat newInstance(
+ @NonNull String rationaleMsg,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String[] permissions) {
+
+ // Create new Fragment
+ RationaleDialogFragmentCompat dialogFragment = new RationaleDialogFragmentCompat();
+
+ // Initialize configuration as arguments
+ RationaleDialogConfig config = new RationaleDialogConfig(
+ positiveButton, negativeButton, rationaleMsg, theme, requestCode, permissions);
+ dialogFragment.setArguments(config.toBundle());
+
+ return dialogFragment;
+ }
+
+ /**
+ * Version of {@link #show(FragmentManager, String)} that no-ops when an IllegalStateException
+ * would otherwise occur.
+ */
+ public void showAllowingStateLoss(FragmentManager manager, String tag) {
+ if (manager.isStateSaved()) {
+ return;
+ }
+
+ show(manager, tag);
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (getParentFragment() != null) {
+ if (getParentFragment() instanceof EasyPermissions.PermissionCallbacks) {
+ mPermissionCallbacks = (EasyPermissions.PermissionCallbacks) getParentFragment();
+ }
+ if (getParentFragment() instanceof EasyPermissions.RationaleCallbacks){
+ mRationaleCallbacks = (EasyPermissions.RationaleCallbacks) getParentFragment();
+ }
+ }
+
+ if (context instanceof EasyPermissions.PermissionCallbacks) {
+ mPermissionCallbacks = (EasyPermissions.PermissionCallbacks) context;
+ }
+
+ if (context instanceof EasyPermissions.RationaleCallbacks) {
+ mRationaleCallbacks = (EasyPermissions.RationaleCallbacks) context;
+ }
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mPermissionCallbacks = null;
+ mRationaleCallbacks = null;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Rationale dialog should not be cancelable
+ setCancelable(false);
+
+ // Get config from arguments, create click listener
+ RationaleDialogConfig config = new RationaleDialogConfig(getArguments());
+ RationaleDialogClickListener clickListener =
+ new RationaleDialogClickListener(this, config, mPermissionCallbacks, mRationaleCallbacks);
+
+ // Create an AlertDialog
+ return config.createSupportDialog(getContext(), clickListener);
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/ActivityPermissionHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/ActivityPermissionHelper.java
new file mode 100644
index 00000000..74aa4228
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/ActivityPermissionHelper.java
@@ -0,0 +1,59 @@
+package pub.devrel.easypermissions.helper;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.StyleRes;
+import androidx.core.app.ActivityCompat;
+import android.util.Log;
+
+import pub.devrel.easypermissions.RationaleDialogFragment;
+
+/**
+ * Permissions helper for {@link Activity}.
+ */
+class ActivityPermissionHelper extends PermissionHelper {
+ private static final String TAG = "ActPermissionHelper";
+
+ public ActivityPermissionHelper(Activity host) {
+ super(host);
+ }
+
+ @Override
+ public void directRequestPermissions(int requestCode, @NonNull String... perms) {
+ ActivityCompat.requestPermissions(getHost(), perms, requestCode);
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(@NonNull String perm) {
+ return ActivityCompat.shouldShowRequestPermissionRationale(getHost(), perm);
+ }
+
+ @Override
+ public Context getContext() {
+ return getHost();
+ }
+
+ @Override
+ public void showRequestPermissionRationale(@NonNull String rationale,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String... perms) {
+ FragmentManager fm = getHost().getFragmentManager();
+
+ // Check if fragment is already showing
+ Fragment fragment = fm.findFragmentByTag(RationaleDialogFragment.TAG);
+ if (fragment instanceof RationaleDialogFragment) {
+ Log.d(TAG, "Found existing fragment, not showing rationale.");
+ return;
+ }
+
+ RationaleDialogFragment
+ .newInstance(positiveButton, negativeButton, rationale, theme, requestCode, perms)
+ .showAllowingStateLoss(fm, RationaleDialogFragment.TAG);
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/AppCompatActivityPermissionsHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/AppCompatActivityPermissionsHelper.java
new file mode 100644
index 00000000..0bc80a59
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/AppCompatActivityPermissionsHelper.java
@@ -0,0 +1,37 @@
+package pub.devrel.easypermissions.helper;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.fragment.app.FragmentManager;
+import androidx.appcompat.app.AppCompatActivity;
+
+/**
+ * Permissions helper for {@link AppCompatActivity}.
+ */
+class AppCompatActivityPermissionsHelper extends BaseSupportPermissionsHelper {
+
+ public AppCompatActivityPermissionsHelper(AppCompatActivity host) {
+ super(host);
+ }
+
+ @Override
+ public FragmentManager getSupportFragmentManager() {
+ return getHost().getSupportFragmentManager();
+ }
+
+ @Override
+ public void directRequestPermissions(int requestCode, @NonNull String... perms) {
+ ActivityCompat.requestPermissions(getHost(), perms, requestCode);
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(@NonNull String perm) {
+ return ActivityCompat.shouldShowRequestPermissionRationale(getHost(), perm);
+ }
+
+ @Override
+ public Context getContext() {
+ return getHost();
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/BaseSupportPermissionsHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/BaseSupportPermissionsHelper.java
new file mode 100644
index 00000000..185da5a2
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/BaseSupportPermissionsHelper.java
@@ -0,0 +1,45 @@
+package pub.devrel.easypermissions.helper;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.StyleRes;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import android.util.Log;
+
+import pub.devrel.easypermissions.RationaleDialogFragmentCompat;
+
+/**
+ * Implementation of {@link PermissionHelper} for Support Library host classes.
+ */
+public abstract class BaseSupportPermissionsHelper extends PermissionHelper {
+
+ private static final String TAG = "BSPermissionsHelper";
+
+ public BaseSupportPermissionsHelper(@NonNull T host) {
+ super(host);
+ }
+
+ public abstract FragmentManager getSupportFragmentManager();
+
+ @Override
+ public void showRequestPermissionRationale(@NonNull String rationale,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String... perms) {
+
+ FragmentManager fm = getSupportFragmentManager();
+
+ // Check if fragment is already showing
+ Fragment fragment = fm.findFragmentByTag(RationaleDialogFragmentCompat.TAG);
+ if (fragment instanceof RationaleDialogFragmentCompat) {
+ Log.d(TAG, "Found existing fragment, not showing rationale.");
+ return;
+ }
+
+ RationaleDialogFragmentCompat
+ .newInstance(rationale, positiveButton, negativeButton, theme, requestCode, perms)
+ .showAllowingStateLoss(fm, RationaleDialogFragmentCompat.TAG);
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/LowApiPermissionsHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/LowApiPermissionsHelper.java
new file mode 100644
index 00000000..6ec74376
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/LowApiPermissionsHelper.java
@@ -0,0 +1,47 @@
+package pub.devrel.easypermissions.helper;
+
+import android.app.Activity;
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.StyleRes;
+import androidx.fragment.app.Fragment;
+
+/**
+ * Permissions helper for apps built against API < 23, which do not need runtime permissions.
+ */
+class LowApiPermissionsHelper extends PermissionHelper {
+ public LowApiPermissionsHelper(@NonNull T host) {
+ super(host);
+ }
+
+ @Override
+ public void directRequestPermissions(int requestCode, @NonNull String... perms) {
+ throw new IllegalStateException("Should never be requesting permissions on API < 23!");
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(@NonNull String perm) {
+ return false;
+ }
+
+ @Override
+ public void showRequestPermissionRationale(@NonNull String rationale,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String... perms) {
+ throw new IllegalStateException("Should never be requesting permissions on API < 23!");
+ }
+
+ @Override
+ public Context getContext() {
+ if (getHost() instanceof Activity) {
+ return (Context) getHost();
+ } else if (getHost() instanceof Fragment) {
+ return ((Fragment) getHost()).getContext();
+ } else {
+ throw new IllegalStateException("Unknown host: " + getHost());
+ }
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/PermissionHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/PermissionHelper.java
new file mode 100644
index 00000000..db95a350
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/PermissionHelper.java
@@ -0,0 +1,113 @@
+package pub.devrel.easypermissions.helper;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Build;
+import androidx.annotation.NonNull;
+import androidx.annotation.StyleRes;
+import androidx.fragment.app.Fragment;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.List;
+
+/**
+ * Delegate class to make permission calls based on the 'host' (Fragment, Activity, etc).
+ */
+public abstract class PermissionHelper {
+
+ private T mHost;
+
+ @NonNull
+ public static PermissionHelper extends Activity> newInstance(Activity host) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return new LowApiPermissionsHelper<>(host);
+ }
+
+ if (host instanceof AppCompatActivity)
+ return new AppCompatActivityPermissionsHelper((AppCompatActivity) host);
+ else {
+ return new ActivityPermissionHelper(host);
+ }
+ }
+
+ @NonNull
+ public static PermissionHelper newInstance(Fragment host) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return new LowApiPermissionsHelper<>(host);
+ }
+
+ return new SupportFragmentPermissionHelper(host);
+ }
+
+ // ============================================================================
+ // Public concrete methods
+ // ============================================================================
+
+ public PermissionHelper(@NonNull T host) {
+ mHost = host;
+ }
+
+ private boolean shouldShowRationale(@NonNull String... perms) {
+ for (String perm : perms) {
+ if (shouldShowRequestPermissionRationale(perm)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void requestPermissions(@NonNull String rationale,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String... perms) {
+ if (shouldShowRationale(perms)) {
+ showRequestPermissionRationale(
+ rationale, positiveButton, negativeButton, theme, requestCode, perms);
+ } else {
+ directRequestPermissions(requestCode, perms);
+ }
+ }
+
+ public boolean somePermissionPermanentlyDenied(@NonNull List perms) {
+ for (String deniedPermission : perms) {
+ if (permissionPermanentlyDenied(deniedPermission)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean permissionPermanentlyDenied(@NonNull String perms) {
+ return !shouldShowRequestPermissionRationale(perms);
+ }
+
+ public boolean somePermissionDenied(@NonNull String... perms) {
+ return shouldShowRationale(perms);
+ }
+
+ @NonNull
+ public T getHost() {
+ return mHost;
+ }
+
+ // ============================================================================
+ // Public abstract methods
+ // ============================================================================
+
+ public abstract void directRequestPermissions(int requestCode, @NonNull String... perms);
+
+ public abstract boolean shouldShowRequestPermissionRationale(@NonNull String perm);
+
+ public abstract void showRequestPermissionRationale(@NonNull String rationale,
+ @NonNull String positiveButton,
+ @NonNull String negativeButton,
+ @StyleRes int theme,
+ int requestCode,
+ @NonNull String... perms);
+
+ public abstract Context getContext();
+
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/SupportFragmentPermissionHelper.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/SupportFragmentPermissionHelper.java
new file mode 100644
index 00000000..cf72eeb3
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/SupportFragmentPermissionHelper.java
@@ -0,0 +1,36 @@
+package pub.devrel.easypermissions.helper;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+
+/**
+ * Permissions helper for {@link Fragment} from the support library.
+ */
+class SupportFragmentPermissionHelper extends BaseSupportPermissionsHelper {
+
+ public SupportFragmentPermissionHelper(@NonNull Fragment host) {
+ super(host);
+ }
+
+ @Override
+ public FragmentManager getSupportFragmentManager() {
+ return getHost().getChildFragmentManager();
+ }
+
+ @Override
+ public void directRequestPermissions(int requestCode, @NonNull String... perms) {
+ getHost().requestPermissions(perms, requestCode);
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(@NonNull String perm) {
+ return getHost().shouldShowRequestPermissionRationale(perm);
+ }
+
+ @Override
+ public Context getContext() {
+ return getHost().getActivity();
+ }
+}
diff --git a/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/package-info.java b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/package-info.java
new file mode 100644
index 00000000..61617bce
--- /dev/null
+++ b/android/easypermissions/src/main/java/pub/devrel/easypermissions/helper/package-info.java
@@ -0,0 +1,4 @@
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+package pub.devrel.easypermissions.helper;
+
+import androidx.annotation.RestrictTo;
diff --git a/android/easypermissions/src/main/res/values/colors.xml b/android/easypermissions/src/main/res/values/colors.xml
new file mode 100644
index 00000000..2ca30829
--- /dev/null
+++ b/android/easypermissions/src/main/res/values/colors.xml
@@ -0,0 +1,7 @@
+
+
+
+ #ff212121
+ @android:color/black
+ #ff80cbc4
+
diff --git a/android/easypermissions/src/main/res/values/strings.xml b/android/easypermissions/src/main/res/values/strings.xml
new file mode 100644
index 00000000..2ceab867
--- /dev/null
+++ b/android/easypermissions/src/main/res/values/strings.xml
@@ -0,0 +1,8 @@
+
+ This app may not work correctly without the requested permissions.
+
+ This app may not work correctly without the requested permissions.
+ Open the app settings screen to modify app permissions.
+
+ Permissions Required
+
diff --git a/android/easypermissions/src/main/res/values/styles.xml b/android/easypermissions/src/main/res/values/styles.xml
new file mode 100644
index 00000000..91239929
--- /dev/null
+++ b/android/easypermissions/src/main/res/values/styles.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/AppSettingsDialogTest.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/AppSettingsDialogTest.java
new file mode 100644
index 00000000..2b353846
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/AppSettingsDialogTest.java
@@ -0,0 +1,186 @@
+package pub.devrel.easypermissions;
+
+import android.app.Application;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.widget.Button;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowIntent;
+
+import java.util.Objects;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.test.core.app.ApplicationProvider;
+import pub.devrel.easypermissions.testhelper.ActivityController;
+import pub.devrel.easypermissions.testhelper.FragmentController;
+import pub.devrel.easypermissions.testhelper.TestActivity;
+import pub.devrel.easypermissions.testhelper.TestFragment;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.robolectric.Shadows.shadowOf;
+import static pub.devrel.easypermissions.AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = 23)
+public class AppSettingsDialogTest {
+
+ private static final String TITLE = "TITLE";
+ private static final String RATIONALE = "RATIONALE";
+ private static final String NEGATIVE = "NEGATIVE";
+ private static final String POSITIVE = "POSITIVE";
+ private ShadowApplication shadowApp;
+ private TestActivity spyActivity;
+ private TestFragment spyFragment;
+ private FragmentController fragmentController;
+ private ActivityController activityController;
+ @Mock
+ private DialogInterface.OnClickListener positiveListener;
+ @Mock
+ private DialogInterface.OnClickListener negativeListener;
+ @Captor
+ private ArgumentCaptor integerCaptor;
+ @Captor
+ private ArgumentCaptor intentCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ shadowApp = shadowOf((Application) ApplicationProvider.getApplicationContext());
+
+ activityController = new ActivityController<>(TestActivity.class);
+ fragmentController = new FragmentController<>(TestFragment.class);
+
+ spyActivity = Mockito.spy(activityController.resume());
+ spyFragment = Mockito.spy(fragmentController.resume());
+ }
+
+ // ------ From Activity ------
+
+ @Test
+ public void shouldShowExpectedSettingsDialog_whenBuildingFromActivity() {
+ new AppSettingsDialog.Builder(spyActivity)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setRationale(android.R.string.unknownName)
+ .setPositiveButton(android.R.string.ok)
+ .setNegativeButton(android.R.string.cancel)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .show();
+
+ verify(spyActivity, times(1))
+ .startActivityForResult(intentCaptor.capture(), integerCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(DEFAULT_SETTINGS_REQ_CODE);
+ assertThat(Objects.requireNonNull(intentCaptor.getValue().getComponent()).getClassName())
+ .isEqualTo(AppSettingsDialogHolderActivity.class.getName());
+
+ Intent startedIntent = shadowApp.getNextStartedActivity();
+ ShadowIntent shadowIntent = shadowOf(startedIntent);
+ assertThat(shadowIntent.getIntentClass()).isEqualTo(AppSettingsDialogHolderActivity.class);
+ }
+
+ @Test
+ public void shouldPositiveListener_whenClickingPositiveButtonFromActivity() {
+ AlertDialog alertDialog = new AppSettingsDialog.Builder(spyActivity)
+ .setTitle(TITLE)
+ .setRationale(RATIONALE)
+ .setPositiveButton(POSITIVE)
+ .setNegativeButton(NEGATIVE)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .showDialog(positiveListener, negativeListener);
+ Button positive = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+ positive.performClick();
+
+ verify(positiveListener, times(1))
+ .onClick(any(DialogInterface.class), anyInt());
+ }
+
+ @Test
+ public void shouldNegativeListener_whenClickingPositiveButtonFromActivity() {
+ AlertDialog alertDialog = new AppSettingsDialog.Builder(spyActivity)
+ .setTitle(TITLE)
+ .setRationale(RATIONALE)
+ .setPositiveButton(POSITIVE)
+ .setNegativeButton(NEGATIVE)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .showDialog(positiveListener, negativeListener);
+ Button positive = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
+ positive.performClick();
+
+ verify(negativeListener, times(1))
+ .onClick(any(DialogInterface.class), anyInt());
+ }
+
+ @Test
+ public void shouldShowExpectedSettingsDialog_whenBuildingFromSupportFragment() {
+ new AppSettingsDialog.Builder(spyFragment)
+ .setTitle(android.R.string.dialog_alert_title)
+ .setRationale(android.R.string.unknownName)
+ .setPositiveButton(android.R.string.ok)
+ .setNegativeButton(android.R.string.cancel)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .show();
+
+ verify(spyFragment, times(1))
+ .startActivityForResult(intentCaptor.capture(), integerCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(DEFAULT_SETTINGS_REQ_CODE);
+ assertThat(Objects.requireNonNull(intentCaptor.getValue().getComponent()).getClassName())
+ .isEqualTo(AppSettingsDialogHolderActivity.class.getName());
+
+ Intent startedIntent = shadowApp.getNextStartedActivity();
+ ShadowIntent shadowIntent = shadowOf(startedIntent);
+ assertThat(shadowIntent.getIntentClass()).isEqualTo(AppSettingsDialogHolderActivity.class);
+ }
+
+ @Test
+ public void shouldPositiveListener_whenClickingPositiveButtonFromSupportFragment() {
+ AlertDialog alertDialog = new AppSettingsDialog.Builder(spyFragment)
+ .setTitle(TITLE)
+ .setRationale(RATIONALE)
+ .setPositiveButton(POSITIVE)
+ .setNegativeButton(NEGATIVE)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .showDialog(positiveListener, negativeListener);
+ Button positive = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+ positive.performClick();
+
+ verify(positiveListener, times(1))
+ .onClick(any(DialogInterface.class), anyInt());
+ }
+
+ @Test
+ public void shouldNegativeListener_whenClickingPositiveButtonFromSupportFragment() {
+ AlertDialog alertDialog = new AppSettingsDialog.Builder(spyFragment)
+ .setTitle(TITLE)
+ .setRationale(RATIONALE)
+ .setPositiveButton(POSITIVE)
+ .setNegativeButton(NEGATIVE)
+ .setThemeResId(R.style.Theme_AppCompat)
+ .build()
+ .showDialog(positiveListener, negativeListener);
+ Button positive = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
+ positive.performClick();
+
+ verify(negativeListener, times(1))
+ .onClick(any(DialogInterface.class), anyInt());
+ }
+
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsLowApiTest.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsLowApiTest.java
new file mode 100644
index 00000000..a6c6976b
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsLowApiTest.java
@@ -0,0 +1,121 @@
+package pub.devrel.easypermissions;
+
+import android.Manifest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+
+import androidx.test.core.app.ApplicationProvider;
+import pub.devrel.easypermissions.testhelper.ActivityController;
+import pub.devrel.easypermissions.testhelper.FragmentController;
+import pub.devrel.easypermissions.testhelper.TestActivity;
+import pub.devrel.easypermissions.testhelper.TestAppCompatActivity;
+import pub.devrel.easypermissions.testhelper.TestFragment;
+import pub.devrel.easypermissions.testhelper.TestSupportFragmentActivity;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Low-API (SDK = 19) tests for {@link pub.devrel.easypermissions.EasyPermissions}.
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = 19)
+public class EasyPermissionsLowApiTest {
+
+ private static final String RATIONALE = "RATIONALE";
+ private static final String[] ALL_PERMS = new String[]{
+ Manifest.permission.READ_SMS, Manifest.permission.ACCESS_FINE_LOCATION};
+
+ private TestActivity spyActivity;
+ private TestSupportFragmentActivity spySupportFragmentActivity;
+ private TestAppCompatActivity spyAppCompatActivity;
+ private TestFragment spyFragment;
+ private FragmentController fragmentController;
+ private ActivityController activityController;
+ private ActivityController supportFragmentActivityController;
+ private ActivityController appCompatActivityController;
+ @Captor
+ private ArgumentCaptor integerCaptor;
+ @Captor
+ private ArgumentCaptor> listCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ activityController = new ActivityController<>(TestActivity.class);
+ supportFragmentActivityController = new ActivityController<>(TestSupportFragmentActivity.class);
+ appCompatActivityController = new ActivityController<>(TestAppCompatActivity.class);
+ fragmentController = new FragmentController<>(TestFragment.class);
+
+ spyActivity = Mockito.spy(activityController.resume());
+ spySupportFragmentActivity = Mockito.spy(supportFragmentActivityController.resume());
+ spyAppCompatActivity = Mockito.spy(appCompatActivityController.resume());
+ spyFragment = Mockito.spy(fragmentController.resume());
+ }
+
+ // ------ General tests ------
+
+ @Test
+ public void shouldHavePermission_whenHasPermissionsBeforeMarshmallow() {
+ assertThat(EasyPermissions.hasPermissions(ApplicationProvider.getApplicationContext(),
+ Manifest.permission.ACCESS_COARSE_LOCATION)).isTrue();
+ }
+
+ // ------ From Activity ------
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestFromActivity() {
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+ // ------ From Support Activity ------
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestFromSupportFragmentActivity() {
+ EasyPermissions.requestPermissions(spySupportFragmentActivity, RATIONALE, TestSupportFragmentActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spySupportFragmentActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestSupportFragmentActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestFromAppCompatActivity() {
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyAppCompatActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestAppCompatActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestFromFragment() {
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyFragment, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestFragment.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsTest.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsTest.java
new file mode 100644
index 00000000..06ce723c
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/EasyPermissionsTest.java
@@ -0,0 +1,611 @@
+package pub.devrel.easypermissions;
+
+import android.Manifest;
+import android.app.Application;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.content.pm.PackageManager;
+import android.widget.TextView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import androidx.test.core.app.ApplicationProvider;
+import pub.devrel.easypermissions.testhelper.ActivityController;
+import pub.devrel.easypermissions.testhelper.FragmentController;
+import pub.devrel.easypermissions.testhelper.TestActivity;
+import pub.devrel.easypermissions.testhelper.TestAppCompatActivity;
+import pub.devrel.easypermissions.testhelper.TestFragment;
+import pub.devrel.easypermissions.testhelper.TestSupportFragmentActivity;
+
+import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+/**
+ * Basic Robolectric tests for {@link pub.devrel.easypermissions.EasyPermissions}.
+ */
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = 23)
+public class EasyPermissionsTest {
+
+ private static final String RATIONALE = "RATIONALE";
+ private static final String POSITIVE = "POSITIVE";
+ private static final String NEGATIVE = "NEGATIVE";
+ private static final String[] ONE_PERM = new String[]{Manifest.permission.READ_SMS};
+ private static final String[] ALL_PERMS = new String[]{
+ Manifest.permission.READ_SMS, Manifest.permission.ACCESS_FINE_LOCATION};
+ private static final int[] SMS_DENIED_RESULT = new int[]{
+ PackageManager.PERMISSION_DENIED, PackageManager.PERMISSION_GRANTED};
+
+ private ShadowApplication shadowApp;
+ private Application app;
+ private TestActivity spyActivity;
+ private TestSupportFragmentActivity spySupportFragmentActivity;
+ private TestAppCompatActivity spyAppCompatActivity;
+ private TestFragment spyFragment;
+ private FragmentController fragmentController;
+ private ActivityController activityController;
+ private ActivityController supportFragmentActivityController;
+ private ActivityController appCompatActivityController;
+ @Captor
+ private ArgumentCaptor integerCaptor;
+ @Captor
+ private ArgumentCaptor> listCaptor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ app = ApplicationProvider.getApplicationContext();
+ shadowApp = shadowOf(app);
+
+ activityController = new ActivityController<>(TestActivity.class);
+ supportFragmentActivityController = new ActivityController<>(TestSupportFragmentActivity.class);
+ appCompatActivityController = new ActivityController<>(TestAppCompatActivity.class);
+ fragmentController = new FragmentController<>(TestFragment.class);
+
+ spyActivity = Mockito.spy(activityController.resume());
+ spySupportFragmentActivity = Mockito.spy(supportFragmentActivityController.resume());
+ spyAppCompatActivity = Mockito.spy(appCompatActivityController.resume());
+ spyFragment = Mockito.spy(fragmentController.resume());
+ }
+
+ // ------ General tests ------
+
+ @Test
+ public void shouldNotHavePermissions_whenNoPermissionsGranted() {
+ assertThat(EasyPermissions.hasPermissions(app, ALL_PERMS)).isFalse();
+ }
+
+ @Test
+ public void shouldNotHavePermissions_whenNotAllPermissionsGranted() {
+ shadowApp.grantPermissions(ONE_PERM);
+ assertThat(EasyPermissions.hasPermissions(app, ALL_PERMS)).isFalse();
+ }
+
+ @Test
+ public void shouldHavePermissions_whenAllPermissionsGranted() {
+ shadowApp.grantPermissions(ALL_PERMS);
+ assertThat(EasyPermissions.hasPermissions(app, ALL_PERMS)).isTrue();
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ @Test
+ public void shouldThrowException_whenHasPermissionsWithNullContext() {
+ try {
+ EasyPermissions.hasPermissions(null, ALL_PERMS);
+ fail("IllegalStateException expected because of null context.");
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessageThat()
+ .isEqualTo("Can't check permissions for null context");
+ }
+ }
+
+ // ------ From Activity ------
+
+ @Test
+ public void shouldCorrectlyCallback_whenOnRequestPermissionResultCalledFromActivity() {
+ EasyPermissions.onRequestPermissionsResult(TestActivity.REQUEST_CODE, ALL_PERMS, SMS_DENIED_RESULT, spyActivity);
+
+ verify(spyActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.ACCESS_FINE_LOCATION)));
+
+ verify(spyActivity, times(1))
+ .onPermissionsDenied(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.READ_SMS)));
+
+ verify(spyActivity, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestAlreadyGrantedPermissionsFromActivity() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ verify(spyActivity, never()).requestPermissions(any(String[].class), anyInt());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+ @Test
+ public void shouldCallbackAfterPermissionGranted_whenRequestAlreadyGrantedPermissionsFromActivity() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ // Called 2 times because this is a spy and library implementation invokes super classes annotated methods as well
+ verify(spyActivity, times(2)).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldNotCallbackAfterPermissionGranted_whenRequestNotGrantedPermissionsFromActivity() {
+ grantPermissions(ONE_PERM);
+
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyActivity, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldRequestPermissions_whenMissingPermissionAndNotShowRationaleFromActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(false, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyActivity, times(1))
+ .requestPermissions(ALL_PERMS, TestActivity.REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialog_whenMissingPermissionsAndShowRationaleFromActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyActivity, RATIONALE, TestActivity.REQUEST_CODE, ALL_PERMS);
+
+ Fragment dialogFragment = spyActivity.getFragmentManager()
+ .findFragmentByTag(RationaleDialogFragment.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragment.class);
+
+ Dialog dialog = ((RationaleDialogFragment) dialogFragment).getDialog();
+ assertThatHasExpectedRationale(dialog, RATIONALE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialogUsingRequest_whenMissingPermissionsAndShowRationaleFromActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ PermissionRequest request = new PermissionRequest.Builder(spyActivity, TestActivity.REQUEST_CODE, ALL_PERMS)
+ .setPositiveButtonText(android.R.string.ok)
+ .setNegativeButtonText(android.R.string.cancel)
+ .setRationale(android.R.string.unknownName)
+ .setTheme(R.style.Theme_AppCompat)
+ .build();
+ EasyPermissions.requestPermissions(request);
+
+ Fragment dialogFragment = spyActivity.getFragmentManager()
+ .findFragmentByTag(RationaleDialogFragment.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragment.class);
+
+ Dialog dialog = ((RationaleDialogFragment) dialogFragment).getDialog();
+ assertThatHasExpectedButtonsAndRationale(dialog, android.R.string.unknownName,
+ android.R.string.ok, android.R.string.cancel);
+ }
+
+ @Test
+ public void shouldHaveSomePermissionDenied_whenShowRationaleFromActivity() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyActivity, ALL_PERMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionDenied_whenNotShowRationaleFromActivity() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyActivity, ALL_PERMS)).isFalse();
+ }
+
+ @Test
+ public void shouldHaveSomePermissionPermanentlyDenied_whenNotShowRationaleFromActivity() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyActivity, Arrays.asList(ALL_PERMS))).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionPermanentlyDenied_whenShowRationaleFromActivity() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyActivity, Arrays.asList(ALL_PERMS))).isFalse();
+ }
+
+ @Test
+ public void shouldHavePermissionPermanentlyDenied_whenNotShowRationaleFromActivity() {
+ showRationale(false, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyActivity, Manifest.permission.READ_SMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHavePermissionPermanentlyDenied_whenShowRationaleFromActivity() {
+ showRationale(true, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyActivity, Manifest.permission.READ_SMS)).isFalse();
+ }
+
+ @Test
+ public void shouldCorrectlyCallback_whenOnRequestPermissionResultCalledFromAppCompatActivity() {
+ EasyPermissions.onRequestPermissionsResult(TestAppCompatActivity.REQUEST_CODE, ALL_PERMS, SMS_DENIED_RESULT, spyAppCompatActivity);
+
+ verify(spyAppCompatActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestAppCompatActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.ACCESS_FINE_LOCATION)));
+
+ verify(spyAppCompatActivity, times(1))
+ .onPermissionsDenied(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestAppCompatActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.READ_SMS)));
+
+ verify(spyAppCompatActivity, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestAlreadyGrantedPermissionsFromAppCompatActivity() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyAppCompatActivity, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ verify(spyAppCompatActivity, never()).requestPermissions(any(String[].class), anyInt());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestAppCompatActivity.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+ @Test
+ public void shouldCallbackAfterPermissionGranted_whenRequestAlreadyGrantedPermissionsFromAppCompatActivity() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ // Called 2 times because this is a spy and library implementation invokes super classes annotated methods as well
+ verify(spyAppCompatActivity, times(2)).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldNotCallbackAfterPermissionGranted_whenRequestNotGrantedPermissionsFromAppCompatActivity() {
+ grantPermissions(ONE_PERM);
+
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyAppCompatActivity, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldRequestPermissions_whenMissingPermissionAndNotShowRationaleFromAppCompatActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(false, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyAppCompatActivity, times(1))
+ .requestPermissions(ALL_PERMS, TestAppCompatActivity.REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialog_whenMissingPermissionsAndShowRationaleFromAppCompatActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyAppCompatActivity, RATIONALE, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS);
+
+ androidx.fragment.app.Fragment dialogFragment = spyAppCompatActivity.getSupportFragmentManager()
+ .findFragmentByTag(RationaleDialogFragmentCompat.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragmentCompat.class);
+
+ Dialog dialog = ((RationaleDialogFragmentCompat) dialogFragment).getDialog();
+ assertThatHasExpectedRationale(dialog, RATIONALE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialog_whenMissingPermissionsAndShowRationaleFromSupportFragmentActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spySupportFragmentActivity, RATIONALE, TestSupportFragmentActivity.REQUEST_CODE, ALL_PERMS);
+
+ Fragment dialogFragment = spySupportFragmentActivity.getFragmentManager()
+ .findFragmentByTag(RationaleDialogFragment.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragment.class);
+
+ Dialog dialog = ((RationaleDialogFragment) dialogFragment).getDialog();
+ assertThatHasExpectedRationale(dialog, RATIONALE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialogUsingRequest_whenMissingPermissionsAndShowRationaleFromAppCompatActivity() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ PermissionRequest request = new PermissionRequest.Builder(spyAppCompatActivity, TestAppCompatActivity.REQUEST_CODE, ALL_PERMS)
+ .setPositiveButtonText(android.R.string.ok)
+ .setNegativeButtonText(android.R.string.cancel)
+ .setRationale(android.R.string.unknownName)
+ .setTheme(R.style.Theme_AppCompat)
+ .build();
+ EasyPermissions.requestPermissions(request);
+
+ androidx.fragment.app.Fragment dialogFragment = spyAppCompatActivity.getSupportFragmentManager()
+ .findFragmentByTag(RationaleDialogFragmentCompat.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragmentCompat.class);
+
+ Dialog dialog = ((RationaleDialogFragmentCompat) dialogFragment).getDialog();
+ assertThatHasExpectedButtonsAndRationale(dialog, android.R.string.unknownName,
+ android.R.string.ok, android.R.string.cancel);
+ }
+
+ @Test
+ public void shouldHaveSomePermissionDenied_whenShowRationaleFromAppCompatActivity() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyAppCompatActivity, ALL_PERMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionDenied_whenNotShowRationaleFromAppCompatActivity() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyAppCompatActivity, ALL_PERMS)).isFalse();
+ }
+
+ @Test
+ public void shouldHaveSomePermissionPermanentlyDenied_whenNotShowRationaleFromAppCompatActivity() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyAppCompatActivity, Arrays.asList(ALL_PERMS))).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionPermanentlyDenied_whenShowRationaleFromAppCompatActivity() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyAppCompatActivity, Arrays.asList(ALL_PERMS))).isFalse();
+ }
+
+ @Test
+ public void shouldHavePermissionPermanentlyDenied_whenNotShowRationaleFromAppCompatActivity() {
+ showRationale(false, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyAppCompatActivity, Manifest.permission.READ_SMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHavePermissionPermanentlyDenied_whenShowRationaleFromAppCompatActivity() {
+ showRationale(true, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyAppCompatActivity, Manifest.permission.READ_SMS)).isFalse();
+ }
+
+ @Test
+ public void shouldCorrectlyCallback_whenOnRequestPermissionResultCalledFromFragment() {
+ EasyPermissions.onRequestPermissionsResult(TestFragment.REQUEST_CODE, ALL_PERMS, SMS_DENIED_RESULT,
+ spyFragment);
+
+ verify(spyFragment, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestFragment.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.ACCESS_FINE_LOCATION)));
+
+ verify(spyFragment, times(1))
+ .onPermissionsDenied(integerCaptor.capture(), listCaptor.capture());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestFragment.REQUEST_CODE);
+ assertThat(listCaptor.getValue())
+ .containsAllIn(new ArrayList<>(Collections.singletonList(Manifest.permission.READ_SMS)));
+
+ verify(spyFragment, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldCallbackOnPermissionGranted_whenRequestAlreadyGrantedPermissionsFromFragment() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE,
+ TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyFragment, times(1))
+ .onPermissionsGranted(integerCaptor.capture(), listCaptor.capture());
+ verify(spyFragment, never()).requestPermissions(any(String[].class), anyInt());
+ assertThat(integerCaptor.getValue()).isEqualTo(TestFragment.REQUEST_CODE);
+ assertThat(listCaptor.getValue()).containsAllIn(ALL_PERMS);
+ }
+
+ @Test
+ public void shouldCallbackAfterPermissionGranted_whenRequestAlreadyGrantedPermissionsFragment() {
+ grantPermissions(ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ // Called 2 times because this is a spy and library implementation invokes super classes annotated methods as well
+ verify(spyFragment, times(2)).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldNotCallbackAfterPermissionGranted_whenRequestNotGrantedPermissionsFromFragment() {
+ grantPermissions(ONE_PERM);
+
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyFragment, never()).afterPermissionGranted();
+ }
+
+ @Test
+ public void shouldRequestPermissions_whenMissingPermissionsAndNotShowRationaleFromFragment() {
+ grantPermissions(ONE_PERM);
+ showRationale(false, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ verify(spyFragment, times(1))
+ .requestPermissions(ALL_PERMS, TestFragment.REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialog_whenMissingPermissionsAndShowRationaleFromFragment() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ EasyPermissions.requestPermissions(spyFragment, RATIONALE, TestFragment.REQUEST_CODE, ALL_PERMS);
+
+ androidx.fragment.app.Fragment dialogFragment = spyFragment.getChildFragmentManager()
+ .findFragmentByTag(RationaleDialogFragmentCompat.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragmentCompat.class);
+
+ Dialog dialog = ((RationaleDialogFragmentCompat) dialogFragment).getDialog();
+ assertThatHasExpectedRationale(dialog, RATIONALE);
+ }
+
+ @Test
+ public void shouldShowCorrectDialogUsingRequest_whenMissingPermissionsAndShowRationaleFromFragment() {
+ grantPermissions(ONE_PERM);
+ showRationale(true, ALL_PERMS);
+
+ PermissionRequest request = new PermissionRequest.Builder(spyFragment, TestFragment.REQUEST_CODE, ALL_PERMS)
+ .setPositiveButtonText(POSITIVE)
+ .setNegativeButtonText(NEGATIVE)
+ .setRationale(RATIONALE)
+ .setTheme(R.style.Theme_AppCompat)
+ .build();
+ EasyPermissions.requestPermissions(request);
+
+ androidx.fragment.app.Fragment dialogFragment = spyFragment.getChildFragmentManager()
+ .findFragmentByTag(RationaleDialogFragmentCompat.TAG);
+ assertThat(dialogFragment).isInstanceOf(RationaleDialogFragmentCompat.class);
+
+ Dialog dialog = ((RationaleDialogFragmentCompat) dialogFragment).getDialog();
+ assertThatHasExpectedButtonsAndRationale(dialog, RATIONALE, POSITIVE, NEGATIVE);
+ }
+
+ @Test
+ public void shouldHaveSomePermissionDenied_whenShowRationaleFromFragment() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyFragment, ALL_PERMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionDenied_whenNotShowRationaleFromFragment() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionDenied(spyFragment, ALL_PERMS)).isFalse();
+ }
+
+ @Test
+ public void shouldHaveSomePermissionPermanentlyDenied_whenNotShowRationaleFromFragment() {
+ showRationale(false, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyFragment, Arrays.asList(ALL_PERMS))).isTrue();
+ }
+
+ @Test
+ public void shouldNotHaveSomePermissionPermanentlyDenied_whenShowRationaleFromFragment() {
+ showRationale(true, ALL_PERMS);
+
+ assertThat(EasyPermissions.somePermissionPermanentlyDenied(spyFragment, Arrays.asList(ALL_PERMS))).isFalse();
+ }
+
+
+ @Test
+ public void shouldHavePermissionPermanentlyDenied_whenNotShowRationaleFromFragment() {
+ showRationale(false, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyFragment, Manifest.permission.READ_SMS)).isTrue();
+ }
+
+ @Test
+ public void shouldNotHavePermissionPermanentlyDenied_whenShowRationaleFromFragment() {
+ showRationale(true, Manifest.permission.READ_SMS);
+
+ assertThat(EasyPermissions.permissionPermanentlyDenied(spyFragment, Manifest.permission.READ_SMS)).isFalse();
+ }
+
+ private void assertThatHasExpectedButtonsAndRationale(Dialog dialog, int rationale,
+ int positive, int negative) {
+ TextView dialogMessage = dialog.findViewById(android.R.id.message);
+ assertThat(dialogMessage.getText().toString()).isEqualTo(app.getString(rationale));
+ TextView positiveMessage = dialog.findViewById(android.R.id.button1);
+ assertThat(positiveMessage.getText().toString()).isEqualTo(app.getString(positive));
+ TextView negativeMessage = dialog.findViewById(android.R.id.button2);
+ assertThat(negativeMessage.getText().toString()).isEqualTo(app.getString(negative));
+ }
+
+ private void assertThatHasExpectedButtonsAndRationale(Dialog dialog, String rationale,
+ int positive, int negative) {
+ TextView dialogMessage = dialog.findViewById(android.R.id.message);
+ assertThat(dialogMessage.getText().toString()).isEqualTo(rationale);
+ TextView positiveMessage = dialog.findViewById(android.R.id.button1);
+ assertThat(positiveMessage.getText().toString()).isEqualTo(app.getString(positive));
+ TextView negativeMessage = dialog.findViewById(android.R.id.button2);
+ assertThat(negativeMessage.getText().toString()).isEqualTo(app.getString(negative));
+ }
+
+ private void assertThatHasExpectedButtonsAndRationale(Dialog dialog, String rationale,
+ String positive, String negative) {
+ TextView dialogMessage = dialog.findViewById(android.R.id.message);
+ assertThat(dialogMessage.getText().toString()).isEqualTo(rationale);
+ TextView positiveMessage = dialog.findViewById(android.R.id.button1);
+ assertThat(positiveMessage.getText().toString()).isEqualTo(positive);
+ TextView negativeMessage = dialog.findViewById(android.R.id.button2);
+ assertThat(negativeMessage.getText().toString()).isEqualTo(negative);
+ }
+
+ private void assertThatHasExpectedRationale(Dialog dialog, String rationale) {
+ TextView dialogMessage = dialog.findViewById(android.R.id.message);
+ assertThat(dialogMessage.getText().toString()).isEqualTo(rationale);
+ }
+
+ private void grantPermissions(String[] perms) {
+ shadowApp.grantPermissions(perms);
+ }
+
+ private void showRationale(boolean show, String... perms) {
+ for (String perm : perms) {
+ when(spyActivity.shouldShowRequestPermissionRationale(perm)).thenReturn(show);
+ when(spySupportFragmentActivity.shouldShowRequestPermissionRationale(perm)).thenReturn(show);
+ when(spyAppCompatActivity.shouldShowRequestPermissionRationale(perm)).thenReturn(show);
+ when(spyFragment.shouldShowRequestPermissionRationale(perm)).thenReturn(show);
+ }
+ }
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/RationaleDialogClickListenerTest.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/RationaleDialogClickListenerTest.java
new file mode 100644
index 00000000..c05f99b1
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/RationaleDialogClickListenerTest.java
@@ -0,0 +1,134 @@
+package pub.devrel.easypermissions;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+
+import androidx.fragment.app.Fragment;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import java.util.Arrays;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = 23)
+public class RationaleDialogClickListenerTest {
+
+ private static final int REQUEST_CODE = 5;
+ private static final String[] PERMS = new String[]{
+ Manifest.permission.READ_SMS, Manifest.permission.ACCESS_FINE_LOCATION};
+ @Mock
+ private RationaleDialogFragment dialogFragment;
+ @Mock
+ private RationaleDialogFragmentCompat dialogFragmentCompat;
+ @Mock
+ private RationaleDialogConfig dialogConfig;
+ @Mock
+ private EasyPermissions.PermissionCallbacks permissionCallbacks;
+ @Mock
+ private EasyPermissions.RationaleCallbacks rationaleCallbacks;
+ @Mock
+ private DialogInterface dialogInterface;
+ @Mock
+ private Activity activity;
+ @Mock
+ private Fragment fragment;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(dialogFragment.getActivity()).thenReturn(activity);
+ dialogConfig.requestCode = REQUEST_CODE;
+ dialogConfig.permissions = PERMS;
+ }
+
+ @Test
+ public void shouldOnRationaleAccepted_whenPositiveButtonWithRationaleCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_POSITIVE);
+
+ verify(rationaleCallbacks, times(1)).onRationaleAccepted(REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldNotOnRationaleAccepted_whenPositiveButtonWithoutRationaleCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, null);
+ listener.onClick(dialogInterface, Dialog.BUTTON_POSITIVE);
+
+ verify(rationaleCallbacks, never()).onRationaleAccepted(anyInt());
+ }
+
+ @Test
+ public void shouldRequestPermissions_whenPositiveButtonFromActivity() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_POSITIVE);
+
+ verify(activity, times(1)).requestPermissions(PERMS, REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldRequestPermissions_whenPositiveButtonFromFragment() {
+ when(dialogFragmentCompat.getParentFragment()).thenReturn(fragment);
+
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragmentCompat, dialogConfig,
+ permissionCallbacks, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_POSITIVE);
+
+ verify(fragment, times(1)).requestPermissions(PERMS, REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldOnRationaleDenied_whenNegativeButtonWithRationaleCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_NEGATIVE);
+
+ verify(rationaleCallbacks, times(1)).onRationaleDenied(REQUEST_CODE);
+ }
+
+ @Test
+ public void shouldNotOnRationaleDenied_whenNegativeButtonWithoutRationaleCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, null);
+ listener.onClick(dialogInterface, Dialog.BUTTON_NEGATIVE);
+
+ verify(rationaleCallbacks, never()).onRationaleDenied(anyInt());
+ }
+
+ @Test
+ public void shouldOnPermissionsDenied_whenNegativeButtonWithPermissionCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ permissionCallbacks, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_NEGATIVE);
+
+ verify(permissionCallbacks, times(1))
+ .onPermissionsDenied(REQUEST_CODE, Arrays.asList(PERMS));
+ }
+
+ @Test
+ public void shouldNotOnPermissionsDenied_whenNegativeButtonWithoutPermissionCallbacks() {
+ RationaleDialogClickListener listener = new RationaleDialogClickListener(dialogFragment, dialogConfig,
+ null, rationaleCallbacks);
+ listener.onClick(dialogInterface, Dialog.BUTTON_NEGATIVE);
+
+ verify(permissionCallbacks, never()).onPermissionsDenied(anyInt(), ArgumentMatchers.anyList());
+ }
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/ActivityController.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/ActivityController.java
new file mode 100644
index 00000000..fc44a2ec
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/ActivityController.java
@@ -0,0 +1,45 @@
+package pub.devrel.easypermissions.testhelper;
+
+import android.app.Activity;
+
+import androidx.annotation.NonNull;
+import androidx.test.core.app.ActivityScenario;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Helper class to allow starting Activity, similar to the Robolectric ActivityConroller.
+ */
+public class ActivityController {
+
+ private ActivityScenario scenario;
+
+ public ActivityController(Class clazz) {
+ scenario = ActivityScenario.launch(clazz);
+ }
+
+ public synchronized T resume() {
+ final CompletableFuture ActivityFuture = new CompletableFuture<>();
+
+ scenario.onActivity(new ActivityScenario.ActivityAction() {
+ @Override
+ public void perform(@NonNull T activity) {
+ ActivityFuture.complete(activity);
+ }
+ });
+
+ try {
+ return ActivityFuture.get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void reset() {
+ scenario.recreate();
+ }
+
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/FragmentController.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/FragmentController.java
new file mode 100644
index 00000000..60447a65
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/FragmentController.java
@@ -0,0 +1,44 @@
+package pub.devrel.easypermissions.testhelper;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.testing.FragmentScenario;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Helper class to allow starting Fragments, similar to the old SupportFragmentController.
+ */
+public class FragmentController {
+
+ private FragmentScenario scenario;
+
+ public FragmentController(Class clazz) {
+ scenario = FragmentScenario.launch(clazz);
+ }
+
+ public synchronized T resume() {
+ final CompletableFuture fragmentFuture = new CompletableFuture<>();
+
+ scenario.onFragment(new FragmentScenario.FragmentAction() {
+ @Override
+ public void perform(@NonNull T fragment) {
+ fragmentFuture.complete(fragment);
+ }
+ });
+
+ try {
+ return fragmentFuture.get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void reset() {
+ scenario.recreate();
+ }
+
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestActivity.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestActivity.java
new file mode 100644
index 00000000..cc1b14c0
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestActivity.java
@@ -0,0 +1,40 @@
+package pub.devrel.easypermissions.testhelper;
+
+import android.app.Activity;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import pub.devrel.easypermissions.AfterPermissionGranted;
+import pub.devrel.easypermissions.EasyPermissions;
+
+public class TestActivity extends Activity
+ implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
+
+ public static final int REQUEST_CODE = 1;
+
+ @Override
+ public void onPermissionsGranted(int requestCode, @NonNull List perms) {
+
+ }
+
+ @Override
+ public void onPermissionsDenied(int requestCode, @NonNull List perms) {
+
+ }
+
+ @AfterPermissionGranted(REQUEST_CODE)
+ public void afterPermissionGranted() {
+
+ }
+
+ @Override
+ public void onRationaleAccepted(int requestCode) {
+
+ }
+
+ @Override
+ public void onRationaleDenied(int requestCode) {
+
+ }
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestAppCompatActivity.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestAppCompatActivity.java
new file mode 100644
index 00000000..3ca8accc
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestAppCompatActivity.java
@@ -0,0 +1,50 @@
+package pub.devrel.easypermissions.testhelper;
+
+import android.os.Bundle;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import pub.devrel.easypermissions.AfterPermissionGranted;
+import pub.devrel.easypermissions.EasyPermissions;
+import pub.devrel.easypermissions.R;
+
+public class TestAppCompatActivity extends AppCompatActivity
+ implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
+
+ public static final int REQUEST_CODE = 3;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ getTheme().applyStyle(R.style.Theme_AppCompat, true);
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onPermissionsGranted(int requestCode, @NonNull List perms) {
+
+ }
+
+ @Override
+ public void onPermissionsDenied(int requestCode, @NonNull List perms) {
+
+ }
+
+ @AfterPermissionGranted(REQUEST_CODE)
+ public void afterPermissionGranted() {
+
+ }
+
+ @Override
+ public void onRationaleAccepted(int requestCode) {
+
+ }
+
+ @Override
+ public void onRationaleDenied(int requestCode) {
+
+ }
+
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestFragment.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestFragment.java
new file mode 100644
index 00000000..96dbbcbe
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestFragment.java
@@ -0,0 +1,55 @@
+package pub.devrel.easypermissions.testhelper;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import pub.devrel.easypermissions.AfterPermissionGranted;
+import pub.devrel.easypermissions.EasyPermissions;
+import pub.devrel.easypermissions.R;
+
+public class TestFragment extends Fragment
+ implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
+
+ public static final int REQUEST_CODE = 4;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ getContext().getTheme().applyStyle(R.style.Theme_AppCompat, true);
+ return super.onCreateView(inflater, container, savedInstanceState);
+ }
+
+ @Override
+ public void onPermissionsGranted(int requestCode, @NonNull List perms) {
+
+ }
+
+ @Override
+ public void onPermissionsDenied(int requestCode, @NonNull List perms) {
+
+ }
+
+ @AfterPermissionGranted(REQUEST_CODE)
+ public void afterPermissionGranted() {
+
+ }
+
+ @Override
+ public void onRationaleAccepted(int requestCode) {
+
+ }
+
+ @Override
+ public void onRationaleDenied(int requestCode) {
+
+ }
+}
diff --git a/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestSupportFragmentActivity.java b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestSupportFragmentActivity.java
new file mode 100644
index 00000000..83187e00
--- /dev/null
+++ b/android/easypermissions/src/test/java/pub/devrel/easypermissions/testhelper/TestSupportFragmentActivity.java
@@ -0,0 +1,47 @@
+package pub.devrel.easypermissions.testhelper;
+
+import android.os.Bundle;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+import pub.devrel.easypermissions.AfterPermissionGranted;
+import pub.devrel.easypermissions.EasyPermissions;
+
+public class TestSupportFragmentActivity extends FragmentActivity
+ implements EasyPermissions.PermissionCallbacks, EasyPermissions.RationaleCallbacks {
+
+ public static final int REQUEST_CODE = 5;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onPermissionsGranted(int requestCode, @NonNull List perms) {
+
+ }
+
+ @Override
+ public void onPermissionsDenied(int requestCode, @NonNull List perms) {
+
+ }
+
+ @AfterPermissionGranted(REQUEST_CODE)
+ public void afterPermissionGranted() {
+
+ }
+
+ @Override
+ public void onRationaleAccepted(int requestCode) {
+
+ }
+
+ @Override
+ public void onRationaleDenied(int requestCode) {
+
+ }
+}
diff --git a/android/settings.gradle b/android/settings.gradle
index 5a2f14fb..90238d2f 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,4 @@
-include ':app'
+include ':app', ':easypermissions'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
diff --git a/assets/images/svgs/add-square.svg b/assets/images/svgs/add-square.svg
new file mode 100644
index 00000000..6c6363f5
--- /dev/null
+++ b/assets/images/svgs/add-square.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/svgs/audit.svg b/assets/images/svgs/audit.svg
new file mode 100644
index 00000000..7d46a569
--- /dev/null
+++ b/assets/images/svgs/audit.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/svgs/delete.svg b/assets/images/svgs/delete.svg
new file mode 100644
index 00000000..7cdd0f32
--- /dev/null
+++ b/assets/images/svgs/delete.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/assets/images/svgs/edit-icon.svg b/assets/images/svgs/edit-icon.svg
new file mode 100644
index 00000000..8fdc3cba
--- /dev/null
+++ b/assets/images/svgs/edit-icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/svgs/edit.svg b/assets/images/svgs/edit.svg
new file mode 100644
index 00000000..586202aa
--- /dev/null
+++ b/assets/images/svgs/edit.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/svgs/favorite.svg b/assets/images/svgs/favorite.svg
new file mode 100644
index 00000000..c9ff828d
--- /dev/null
+++ b/assets/images/svgs/favorite.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/assets/images/svgs/favoriteadded.svg b/assets/images/svgs/favoriteadded.svg
new file mode 100644
index 00000000..3b4577cf
--- /dev/null
+++ b/assets/images/svgs/favoriteadded.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/assets/images/svgs/information.svg b/assets/images/svgs/information.svg
new file mode 100644
index 00000000..5ec862f2
--- /dev/null
+++ b/assets/images/svgs/information.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/assets/images/svgs/resolve.svg b/assets/images/svgs/resolve.svg
new file mode 100644
index 00000000..51d064f3
--- /dev/null
+++ b/assets/images/svgs/resolve.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/images/svgs/save_as_draft.svg b/assets/images/svgs/save_as_draft.svg
new file mode 100644
index 00000000..a06e6b69
--- /dev/null
+++ b/assets/images/svgs/save_as_draft.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/assets/images/svgs/unavailable.svg b/assets/images/svgs/unavailable.svg
new file mode 100644
index 00000000..7e692d97
--- /dev/null
+++ b/assets/images/svgs/unavailable.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index f27854e0..f10a0117 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -196,7 +196,11 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
C21500C474806845DCE7C12A /* [CP] Embed Pods Frameworks */,
+<<<<<<< HEAD
2F366CF6754687244D8F7616 /* [CP] Copy Pods Resources */,
+=======
+ 294E280337160E3088FD37C0 /* [CP] Copy Pods Resources */,
+>>>>>>> b8ae0cf7d0bab766e883756683c22cb5e7a6d396
);
buildRules = (
);
@@ -213,7 +217,8 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1430;
+ BuildIndependentTargetsInParallel = YES;
+ LastUpgradeCheck = 1500;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -257,7 +262,11 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
+<<<<<<< HEAD
2F366CF6754687244D8F7616 /* [CP] Copy Pods Resources */ = {
+=======
+ 294E280337160E3088FD37C0 /* [CP] Copy Pods Resources */ = {
+>>>>>>> b8ae0cf7d0bab766e883756683c22cb5e7a6d396
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -484,6 +493,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -494,6 +504,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -502,7 +513,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -568,6 +579,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -578,6 +590,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -592,7 +605,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -624,6 +637,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -634,6 +648,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -642,10 +657,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -658,8 +674,46 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
+<<<<<<< HEAD
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 1;
+=======
+ CURRENT_PROJECT_VERSION = 4;
+ DEVELOPMENT_TEAM = 3A359E86ZF;
+ ENABLE_BITCODE = NO;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ INFOPLIST_FILE = Runner/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/Flutter",
+ );
+ MARKETING_VERSION = 1.3.99;
+ PRODUCT_BUNDLE_IDENTIFIER = com.hmg.hmgDr;
+ PRODUCT_NAME = Runner;
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = C8801C5E6B82B6CB497CA5C7 /* Pods-Runner.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/RunnerRelease.entitlements;
+ CURRENT_PROJECT_VERSION = 4;
+>>>>>>> b8ae0cf7d0bab766e883756683c22cb5e7a6d396
DEVELOPMENT_TEAM = 3A359E86ZF;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..f9b0d7c5
--- /dev/null
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index 4ba725f4..0b02bfc6 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 8ebd4235..34cf8386 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -4,7 +4,7 @@ import OpenTok
// Created by Mohammad Aljammal & Elham Rababah on 24/06/20.
// Copyright © 2020 Cloud. All rights reserved.
-@UIApplicationMain
+@main
@objc class AppDelegate: FlutterAppDelegate ,ICallProtocol {
var result: FlutterResult?
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 00000000..dc9ada47
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift
new file mode 100644
index 00000000..86a7c3b1
--- /dev/null
+++ b/ios/RunnerTests/RunnerTests.swift
@@ -0,0 +1,12 @@
+import Flutter
+import UIKit
+import XCTest
+
+class RunnerTests: XCTestCase {
+
+ func testExample() {
+ // If you add code to the Runner application, consider adding tests here.
+ // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
+ }
+
+}
diff --git a/lib/client/base_app_client.dart b/lib/client/base_app_client.dart
index 7c06836d..5747ccb4 100644
--- a/lib/client/base_app_client.dart
+++ b/lib/client/base_app_client.dart
@@ -8,6 +8,8 @@ import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/core/service/NavigationService.dart';
import 'package:doctor_app_flutter/core/viewModel/authentication_view_model.dart';
import 'package:doctor_app_flutter/utils/dr_app_shared_pref.dart';
+import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart';
+import 'package:doctor_app_flutter/utils/exception_report.dart';
import 'package:doctor_app_flutter/utils/utils.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
@@ -23,11 +25,11 @@ class BaseAppClient {
//TODO change the post fun to nun static when you change all service
post(String endPoint,
{Map? body,
- required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- bool isAllowAny = false,
- bool isLiveCare = false,
- bool isFallLanguage = false}) async {
+ required Function(dynamic response, int statusCode) onSuccess,
+ required Function(String error, int statusCode) onFailure,
+ bool isAllowAny = false,
+ bool isLiveCare = false,
+ bool isFallLanguage = false}) async {
String url;
if (isLiveCare)
url = BASE_URL_LIVE_CARE + endPoint;
@@ -44,7 +46,9 @@ class BaseAppClient {
if (body == null || body['DoctorID'] == null) {
body!['DoctorID'] = doctorProfile.doctorID;
}
- if (body['DoctorID'] == "") body['DoctorID'] = null;
+ if (body['DoctorID'] == "")
+ body['DoctorID'] = doctorProfile
+ .doctorID; // changed from null; because create update episode not working
if (body['EditedBy'] == null) body['EditedBy'] = doctorProfile.doctorID;
if (body['ProjectID'] == null) {
body['ProjectID'] = doctorProfile.projectID;
@@ -60,8 +64,8 @@ class BaseAppClient {
body['SetupID'] = body.containsKey('SetupID')
? body['SetupID'] != null
- ? body['SetupID']
- : await sharedPref.getString(DOCTOR_SETUP_ID)
+ ? body['SetupID']
+ : await sharedPref.getString(DOCTOR_SETUP_ID)
: await sharedPref.getString(DOCTOR_SETUP_ID);
if (body['EditedBy'] == '') {
@@ -90,16 +94,21 @@ class BaseAppClient {
body['IsLoginForDoctorApp'] = IS_LOGIN_FOR_DOCTOR_APP;
body['PatientOutSA'] = body['PatientOutSA'] ?? 0; // PATIENT_OUT_SA;
if (body['VidaAuthTokenID'] == null) {
- body['VidaAuthTokenID'] = await sharedPref.getString(VIDA_AUTH_TOKEN_ID);
+ body['VidaAuthTokenID'] =
+ await sharedPref.getString(VIDA_AUTH_TOKEN_ID);
}
if (body['VidaRefreshTokenID'] == null) {
- body['VidaRefreshTokenID'] = await sharedPref.getString(VIDA_REFRESH_TOKEN_ID);
+ body['VidaRefreshTokenID'] =
+ await sharedPref.getString(VIDA_REFRESH_TOKEN_ID);
}
int? projectID = await sharedPref.getInt(PROJECT_ID);
if (projectID == 2 || projectID == 3)
body['PatientOutSA'] = true;
- else if ((body.containsKey('facilityId') && body['facilityId'] == 2 || body['facilityId'] == 3) || body['ProjectID'] == 2 || body['ProjectID'] == 3)
+ else if ((body.containsKey('facilityId') && body['facilityId'] == 2 ||
+ body['facilityId'] == 3) ||
+ body['ProjectID'] == 2 ||
+ body['ProjectID'] == 3)
body['PatientOutSA'] = true;
else
body['PatientOutSA'] = false;
@@ -126,26 +135,48 @@ class BaseAppClient {
var asd = json.encode(body);
var asd2;
if (await Utils.checkConnection()) {
- final response = await http.post(Uri.parse(url), body: json.encode(body), headers: {'Content-Type': 'application/json', 'Accept': 'application/json'});
+ final response = await http.post(Uri.parse(url),
+ body: json.encode(body),
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json'
+ });
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400) {
onFailure(Utils.generateContactAdminMsg(), statusCode);
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: "$statusCode");
} else {
var parsed = json.decode(response.body.toString());
if (parsed['ErrorType'] == 4) {
- helpers.navigateToUpdatePage(parsed['ErrorEndUserMessage'], parsed['AndroidLink'], parsed['IOSLink']);
+ helpers.navigateToUpdatePage(parsed['ErrorEndUserMessage'],
+ parsed['AndroidLink'], parsed['IOSLink']);
}
if (parsed['IsAuthenticated'] != null && !parsed['IsAuthenticated']) {
if (body['OTP_SendType'] != null) {
- if(parsed['ErrorCode'] =='699'){
- onSuccess(parsed, statusCode);
- }else {
- onFailure(getError(parsed), statusCode);
- }
+ if (parsed['ErrorCode'] == '699') {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: getError(parsed));
+ onFailure(getError(parsed), statusCode);
+ }
} else if (!isAllowAny) {
- await Provider.of(AppGlobal.CONTEX, listen: false).logout();
-
+ await Provider.of(AppGlobal.CONTEX,
+ listen: false)
+ .logout();
+ //todo nofailure is placed here and but have to handle the response here as well
Utils.showErrorToast('Your session expired Please login again');
locator().pushNamedAndRemoveUntil(ROOT);
}
@@ -153,15 +184,39 @@ class BaseAppClient {
onFailure(getError(parsed), statusCode);
}
} else if (parsed['MessageStatus'] == 1) {
- if (!parsed['IsAuthenticated'])
+ if (!parsed['IsAuthenticated']) {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: getError(parsed));
onFailure(getError(parsed), statusCode);
- else
+ } else
onSuccess(parsed, statusCode);
} else {
- onFailure(getError(parsed), statusCode);
+ final validations = parsed['ValidationErrorsCSI']?['errors']?['Validations'];
+
+ if (validations is List && validations.isNotEmpty) {
+ final error = validations.first['Error'];
+ if (error != null) {
+ onFailure(error, statusCode);
+ return;
+ }
+ }
+ if (body['DoctorID'] != null) {
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: getError(parsed));
+ }
+ onFailure(getError(parsed), statusCode);
+ }
}
- }
- } else {
+ } else {
onFailure('Please Check The Internet Connection', -1);
}
} catch (e) {
@@ -170,187 +225,264 @@ class BaseAppClient {
}
}
- postPatient(String endPoint,
- {Map? body,
- required Function(dynamic response, int statusCode) onSuccess,
- required Function(String error, int statusCode) onFailure,
- PatiantInformtion? patient,
- bool isExternal = false}) async {
+ postPatient(String endPoint,
+ {Map? body,
+ required Function(dynamic response, int statusCode) onSuccess,
+ required Function(String error, int statusCode) onFailure,
+ PatiantInformtion? patient,
+ bool isExternal = false}) async {
String url = BASE_URL + endPoint;
try {
- Map headers = {'Content-Type': 'application/json', 'Accept': 'application/json'};
-
- String? token = await sharedPref.getString(TOKEN);
- Map? profile = await sharedPref.getObj(DOCTOR_PROFILE);
-
- if (profile != null) {
- DoctorProfileModel doctorProfile = DoctorProfileModel.fromJson(profile);
- if (body!['DoctorID'] == null) {
- body['DoctorID'] = doctorProfile.doctorID;
- }
- }
- if (body!['DoctorID'] == 0) {
- body['DoctorID'] = null;
- }
- var languageID = await sharedPref.getStringWithDefaultValue(APP_Language, 'en');
- body['SetupID'] = body!.containsKey('SetupID')
- ? body['SetupID'] != null
- ? body['SetupID']
- : await sharedPref.getString(DOCTOR_SETUP_ID)
- : await sharedPref.getString(DOCTOR_SETUP_ID);
-
- body['VersionID'] = VERSION_ID;
- body['Channel'] = CHANNEL;
- body['LanguageID'] = languageID == 'ar' ? 1 : 2;
-
- body['IPAdress'] = "10.20.10.20";
- body['generalid'] = GENERAL_ID;
- body['PatientOutSA'] = body.containsKey('PatientOutSA')
- ? body['PatientOutSA'] != null
- ? body['PatientOutSA']
- : PATIENT_OUT_SA_PATIENT_REQ
- : PATIENT_OUT_SA_PATIENT_REQ;
-
- if (body.containsKey('isDentalAllowedBackend')) {
- body['isDentalAllowedBackend'] = body.containsKey('isDentalAllowedBackend')
- ? body['isDentalAllowedBackend'] != null
- ? body['isDentalAllowedBackend']
- : IS_DENTAL_ALLOWED_BACKEND
- : IS_DENTAL_ALLOWED_BACKEND;
- }
-
- body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2;
-
- body['PatientType'] = body.containsKey('PatientType')
- ? body['PatientType'] != null
- ? body['PatientType']
- : patient!.patientType != null
- ? patient.patientType
- : PATIENT_TYPE
- : PATIENT_TYPE;
-
- body['PatientTypeID'] = body.containsKey('PatientTypeID')
- ? body['PatientTypeID'] != null
- ? body['PatientTypeID']
- : patient!.patientType != null
- ? patient.patientType
- : PATIENT_TYPE_ID
- : PATIENT_TYPE_ID;
-
- body['TokenID'] = body.containsKey('TokenID') ? body['TokenID'] ?? token : token;
- body['PatientID'] = body['PatientID'] != null ? body['PatientID'] : patient!.patientId ?? patient.patientMRN;
-
- body['PatientOutSA'] = 0; //user['OutSA']; //TODO change it
- body['SessionID'] = SESSION_ID; //getSe
-
- int? projectID = await sharedPref.getInt(PROJECT_ID);
- if (projectID == 2 || projectID == 3)
- body['PatientOutSA'] = true;
- else
- body['PatientOutSA'] = false;
-
- // if(!body.containsKey('ProjectID')) {
- // if (projectID != null) {
- // body['ProjectID'] = 313;
- // } else {
- // body['ProjectID'] = 0;
- // }
- // }
-
- // body['DoctorID'] = 24; //3844083
- // body['TokenID'] = "@dm!n";
+ Map headers = {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json'
+ };
+
+ String? token = await sharedPref.getString(TOKEN);
+ Map? profile = await sharedPref.getObj(DOCTOR_PROFILE);
+
+ if (profile != null) {
+ DoctorProfileModel doctorProfile = DoctorProfileModel.fromJson(profile);
+ if (body!['DoctorID'] == null) {
+ body['DoctorID'] = doctorProfile.doctorID;
+ }
+ }
+ if (body!['DoctorID'] == 0) {
+ body['DoctorID'] = null;
+ }
+ var languageID =
+ await sharedPref.getStringWithDefaultValue(APP_Language, 'en');
+ body['SetupID'] = body!.containsKey('SetupID')
+ ? body['SetupID'] != null
+ ? body['SetupID']
+ : await sharedPref.getString(DOCTOR_SETUP_ID)
+ : await sharedPref.getString(DOCTOR_SETUP_ID);
+
+ body['VersionID'] = VERSION_ID;
+ body['Channel'] = CHANNEL;
+ body['LanguageID'] = languageID == 'ar' ? 1 : 2;
+
+ body['IPAdress'] = "10.20.10.20";
+ body['generalid'] = GENERAL_ID;
+ body['PatientOutSA'] = body.containsKey('PatientOutSA')
+ ? body['PatientOutSA'] != null
+ ? body['PatientOutSA']
+ : PATIENT_OUT_SA_PATIENT_REQ
+ : PATIENT_OUT_SA_PATIENT_REQ;
+
+ if (body.containsKey('isDentalAllowedBackend')) {
+ body['isDentalAllowedBackend'] =
+ body.containsKey('isDentalAllowedBackend')
+ ? body['isDentalAllowedBackend'] != null
+ ? body['isDentalAllowedBackend']
+ : IS_DENTAL_ALLOWED_BACKEND
+ : IS_DENTAL_ALLOWED_BACKEND;
+ }
- print("URL : $url");
- print("Body : ${json.encode(body)}");
- var asd = json.encode(body);
- var asd2;
- if (await Utils.checkConnection()) {
- final response = await http.post(Uri.parse(url.trim()), body: json.encode(body), headers: headers);
- final int statusCode = response.statusCode;
- print("statusCode :$statusCode");
- if (statusCode < 200 || statusCode >= 400 || json == null) {
- onFailure('Error While Fetching data', statusCode);
- } else {
- // var parsed = json.decode(response.body.toString());
- var parsed = json.decode(utf8.decode(response.bodyBytes));
- if (parsed['Response_Message'] != null) {
- onSuccess(parsed, statusCode);
- } else {
- if (parsed['ErrorType'] == 4) {
- helpers.navigateToUpdatePage(parsed['ErrorEndUserMessage'], parsed['AndroidLink'], parsed['IOSLink']);
- }
- if (parsed['IsAuthenticated'] == null) {
- if (parsed['isSMSSent'] == true) {
- onSuccess(parsed, statusCode);
- } else if (parsed['MessageStatus'] == 1) {
- onSuccess(parsed, statusCode);
- } else if (parsed['Result'] == 'OK') {
- onSuccess(parsed, statusCode);
- } else {
- if (parsed != null) {
- onSuccess(parsed, statusCode);
- } else {
- onFailure(getError(parsed), statusCode);
- }
- }
- } else if (parsed['MessageStatus'] == 1 || parsed['SMSLoginRequired'] == true) {
- onSuccess(parsed, statusCode);
- } else if (parsed['MessageStatus'] == 2 && parsed['IsAuthenticated']) {
- if (parsed['SameClinicApptList'] != null) {
- onSuccess(parsed, statusCode);
- } else {
- if (parsed['message'] == null && parsed['ErrorEndUserMessage'] == null) {
- if (parsed['ErrorSearchMsg'] == null) {
- onFailure("Server Error found with no available message", statusCode);
- } else {
- onFailure(parsed['ErrorSearchMsg'], statusCode);
- }
- } else {
- onFailure(parsed['message'] ?? parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
- }
- }
- } else {
- if (parsed['SameClinicApptList'] != null) {
- onSuccess(parsed, statusCode);
- } else {
- if (parsed['message'] != null) {
- onFailure(parsed['message'] ?? parsed['message'], statusCode);
- } else {
- onFailure(parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'], statusCode);
- }
- }
- }
- }
- }
- } else {
- onFailure('Please Check The Internet Connection', -1);
- }
+ body['DeviceTypeID'] = Platform.isAndroid ? 1 : 2;
+
+ body['PatientType'] = body.containsKey('PatientType')
+ ? body['PatientType'] != null
+ ? body['PatientType']
+ : patient!.patientType != null
+ ? patient.patientType
+ : PATIENT_TYPE
+ : PATIENT_TYPE;
+
+ body['PatientTypeID'] = body.containsKey('PatientTypeID')
+ ? body['PatientTypeID'] != null
+ ? body['PatientTypeID']
+ : patient!.patientType != null
+ ? patient.patientType
+ : PATIENT_TYPE_ID
+ : PATIENT_TYPE_ID;
+
+ body['TokenID'] =
+ body.containsKey('TokenID') ? body['TokenID'] ?? token : token;
+ body['PatientID'] = body['PatientID'] != null
+ ? body['PatientID']
+ : patient!.patientId ?? patient.patientMRN;
+
+ body['PatientOutSA'] = 0; //user['OutSA']; //TODO change it
+ body['SessionID'] = SESSION_ID; //getSe
+
+ int? projectID = await sharedPref.getInt(PROJECT_ID);
+ if (projectID == 2 || projectID == 3)
+ body['PatientOutSA'] = true;
+ else
+ body['PatientOutSA'] = false;
+
+ // if(!body.containsKey('ProjectID')) {
+ // if (projectID != null) {
+ // body['ProjectID'] = 313;
+ // } else {
+ // body['ProjectID'] = 0;
+ // }
+ // }
+
+ // body['DoctorID'] = 24; //3844083
+ // body['TokenID'] = "@dm!n";
+
+ print("URL : $url");
+ print("Body : ${json.encode(body)}");
+ var asd = json.encode(body);
+ var asd2;
+ if (await Utils.checkConnection()) {
+ final response = await http.post(Uri.parse(url.trim()),
+ body: json.encode(body), headers: headers);
+ final int statusCode = response.statusCode;
+ print("statusCode :$statusCode");
+ if (statusCode < 200 || statusCode >= 400 || json == null) {
+ onFailure('Error While Fetching data', statusCode);
+ } else {
+ // var parsed = json.decode(response.body.toString());
+ var parsed = json.decode(utf8.decode(response.bodyBytes));
+ if (parsed['Response_Message'] != null) {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (parsed['ErrorType'] == 4) {
+ helpers.navigateToUpdatePage(parsed['ErrorEndUserMessage'],
+ parsed['AndroidLink'], parsed['IOSLink']);
+ }
+ if (parsed['IsAuthenticated'] == null) {
+ if (parsed['isSMSSent'] == true) {
+ onSuccess(parsed, statusCode);
+ } else if (parsed['MessageStatus'] == 1) {
+ onSuccess(parsed, statusCode);
+ } else if (parsed['Result'] == 'OK') {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (parsed != null) {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: getError(parsed));
+ onFailure(getError(parsed), statusCode);
+ }
+ }
+ } else if (parsed['MessageStatus'] == 1 ||
+ parsed['SMSLoginRequired'] == true) {
+ onSuccess(parsed, statusCode);
+ } else if (parsed['MessageStatus'] == 2 &&
+ parsed['IsAuthenticated']) {
+ if (parsed['SameClinicApptList'] != null) {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (parsed['message'] == null &&
+ parsed['ErrorEndUserMessage'] == null) {
+ if (parsed['ErrorSearchMsg'] == null) {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception:
+ "Server Error found with no available message");
+
+ onFailure("Server Error found with no available message",
+ statusCode);
+ } else {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: parsed['ErrorSearchMsg']);
+ onFailure(parsed['ErrorSearchMsg'], statusCode);
+ }
+ } else {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: parsed['message'] ??
+ parsed['ErrorEndUserMessage'] ??
+ parsed['ErrorMessage']);
+ onFailure(
+ parsed['message'] ??
+ parsed['ErrorEndUserMessage'] ??
+ parsed['ErrorMessage'],
+ statusCode);
+ }
+ }
+ } else {
+ if (parsed['SameClinicApptList'] != null) {
+ onSuccess(parsed, statusCode);
+ } else {
+ if (parsed['message'] != null) {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: parsed['message']);
+
+ onFailure(parsed['message'] ?? parsed['message'], statusCode);
+ } else {
+ if (body['DoctorID'] != null)
+ postFailureResponse(
+ doctorId: body['DoctorID'],
+ url: url,
+ request: json.encode(body),
+ response: response.body,
+ exception: parsed['ErrorEndUserMessage'] ??
+ parsed['ErrorMessage']);
+
+ onFailure(
+ parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'],
+ statusCode);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ onFailure('Please Check The Internet Connection', -1);
+ }
} catch (e) {
- print(e);
- onFailure(e.toString(), -1);
+ print(e);
+ onFailure(e.toString(), -1);
+ }
}
- }
- String getError(parsed) {
+ String getError(parsed) {
//TODO change this fun
String? error = parsed['ErrorEndUserMessage'] ?? parsed['ErrorMessage'];
if (parsed["ValidationErrors"] != null) {
- error = parsed["ValidationErrors"]["StatusMessage"].toString() + "\n";
-
- if (parsed["ValidationErrors"]["ValidationErrors"] != null && parsed["ValidationErrors"]["ValidationErrors"].length != 0) {
- for (var i = 0; i < parsed["ValidationErrors"]["ValidationErrors"].length; i++) {
- error = error! + parsed["ValidationErrors"]["ValidationErrors"][i]["Messages"][0] + "\n";
- }
- }
+ error = parsed["ValidationErrors"]["StatusMessage"].toString() + "\n";
+
+ if (parsed["ValidationErrors"]["ValidationErrors"] != null &&
+ parsed["ValidationErrors"]["ValidationErrors"].length != 0) {
+ for (var i = 0;
+ i < parsed["ValidationErrors"]["ValidationErrors"].length;
+ i++) {
+ error = error! +
+ parsed["ValidationErrors"]["ValidationErrors"][i]["Messages"][0] +
+ "\n";
+ }
+ }
}
if (error == null || error == "null" || error == "null\n") {
- return Utils.generateContactAdminMsg();
+ return Utils.generateContactAdminMsg();
}
return error;
- }
+ }
- get({required String endPoint, required Function(dynamic response, int statusCode) onSuccess, required Function(String error, int statusCode) onFailure}) async {
+ get(
+ {required String endPoint,
+ required Function(dynamic response, int statusCode) onSuccess,
+ required Function(String error, int statusCode) onFailure}) async {
String token = await sharedPref.getString(TOKEN);
String url = DOCTOR_ROTATION + endPoint + '&token=' + token;
print(url);
@@ -358,10 +490,10 @@ class BaseAppClient {
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode >= 400) {
- onFailure(Utils.generateContactAdminMsg(), statusCode);
+ onFailure(Utils.generateContactAdminMsg(), statusCode);
} else {
- var parsed = json.decode(response.body.toString());
- onSuccess(parsed, statusCode);
+ var parsed = json.decode(response.body.toString());
+ onSuccess(parsed, statusCode);
+ }
}
}
-}
diff --git a/lib/config/config.dart b/lib/config/config.dart
index b8c88b61..de76d5d1 100644
--- a/lib/config/config.dart
+++ b/lib/config/config.dart
@@ -12,6 +12,10 @@ const BASE_URL_LIVE_CARE = 'https://uat.hmgwebservices.com/';
// const BASE_URL = 'http://10.20.200.111:1010/';
const BASE_URL = 'https://uat.hmgwebservices.com/';
+// const BASE_URL = 'https://hmgwebservices.com/';
+
+// const BASE_URL = 'https://uat.hmgwebservices.com/';
+
// const BASE_URL = 'https://webservices.hmg.com/';
// const BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; //Vida Plus URL
@@ -286,6 +290,88 @@ const DOCTOR_RADIOLOGY_CRITICAL_FINDINGS = "Services/DoctorApplication.svc/REST/
const ACKNOWLEDGE_RADIOLOGY_CRITICAL_FINDINGS = "Services/DoctorApplication.svc/REST/Acknowledgeradcriticalfindings";
+
+ /*vida plus API */
+
+const PATIENT_ALLERGIES = 'Services/DoctorApplication.svc/REST/PatientAllergies';
+
+const SEARCH_ALLERGIES = 'Services/DoctorApplication.svc/REST/SearchAllergies';
+
+const POST_ALLERGIES = 'Services/DoctorApplication.svc/REST/PostAllergies';
+
+const CREATE_HOPI = 'Services/DoctorApplication.svc/REST/CreateHOPI';
+
+const HOPI_DETAILS = 'Services/DoctorApplication.svc/REST/DetailHOPI';
+
+const POST_CHIEF_COMPLAINT_VP = 'Services/DoctorApplication.svc/REST/PostChiefcomplaint';
+
+const SEARCH_CHIEF_COMPLAINT_VP = 'Services/DoctorApplication.svc/REST/SearchChiefcomplaint';
+
+const RESOLVE_ALLERGIES = 'Services/DoctorApplication.svc/REST/ResolveAllergy';
+
+const UPDATE_ALLERGIES = 'Services/DoctorApplication.svc/REST/UpdateAllergy';
+
+const GET_CHIEF_COMPLAINT_VP = 'Services/DoctorApplication.svc/REST/ChiefComplaintDetails';
+
+const SEARCH_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/SearchDiagnosis';
+
+const DIAGNOSIS_TYPE = 'Services/DoctorApplication.svc/REST/DiagnosisType';
+
+const CONDITION_TYPE = 'Services/DoctorApplication.svc/REST/DiagnosisCondition';
+
+const CREATE_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/CreateDiagnosis';
+
+const PREVIOUS_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisPreviousDetails';
+
+const AUDIT_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisAudit';
+
+const REMOVE_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisRemove';
+
+const FAVORITE_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisGetFavourite';
+
+const ADD_TO_FAVORITE_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisAddFavourite';
+
+const MAKE_PREVIOUS_AS_CURRENT_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/ContinuePreviousEpisode';
+
+const SEARCH_PHYSICAL_EXAMINATION = 'Services/DoctorApplication.svc/REST/SearchPhysicalExam';
+
+const GET_GENERAL_SPECIALITY = 'Services/DoctorApplication.svc/REST/GetGeneralSpeciality';
+
+const GET_SPECIALITY_DETAILS = 'Services/DoctorApplication.svc/REST/SearchGeneralSpeciality';
+
+const POST_PHYSICAL_EXAMINATION = 'Services/DoctorApplication.svc/REST/PostPhysicalExam';
+
+const GET_PROGRESS_NOTE_NEW = 'Services/DoctorApplication.svc/REST/GetProgressNote';
+
+const GET_LIST_OF_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisDetailsSearch';
+
+const EDIT_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/EditDiagnosis';
+
+const RESOLVE_DIAGNOSIS = 'Services/DoctorApplication.svc/REST/DiagnosisResolve';
+const GET_CLINIC = 'Services/DoctorApplication.svc/REST/GetDoctorClinicsForVidaPlus';
+
+const CONTINUE_EPISODE_VP = 'Services/DoctorApplication.svc/REST/ContinueEpisode';
+
+const UPDATE_CHIEF_COMPLAINT = 'Services/DoctorApplication.svc/REST/UpdateChiefComplaint';
+
+const EPISODE_BY_CHIEF_COMPLAINT = 'Services/DoctorApplication.svc/REST/EpisodeByChiefcomplaint';
+
+const GET_EDIT_ALLERGIES = 'Services/DoctorApplication.svc/REST/GetAllergy';
+
+const GET_HOME_MEDICATION = 'Services/DoctorApplication.svc/REST/GetHomeMedication';
+
+const SEARCH_CURRENT_MEDICATION = 'Services/DoctorApplication.svc/REST/SearchFormulary';
+
+const SEARCH_CURRENT_MEDICATION_DETAILS = 'Services/DoctorApplication.svc/REST/GetFormularyMaster';
+
+const REMOVE_CURRENT_MEDICATION = 'Services/DoctorApplication.svc/REST/DeleteHomeMedication';
+
+const ADD_CURRENT_MEDICATION = 'Services/DoctorApplication.svc/REST/AddHomeMedication';
+
+const CREATE_PROGRESS_NOTE = 'Services/DoctorApplication.svc/REST/PostProgressNote';
+
+const GET_PATIENT_CLINIC = 'Services/DoctorApplication.svc/REST/GetPatientConditionProgress';
+
var selectedPatientType = 1;
//*********change value to decode json from Dropdown ************
@@ -318,7 +404,7 @@ const TRANSACTION_NO = 0;
const LANGUAGE_ID = 2;
const STAMP = '2020-04-27T12:17:17.721Z';
const IP_ADDRESS = '9.9.9.9';
-const VERSION_ID = 8.9;
+const VERSION_ID = 9.4;
const CHANNEL = 9;
const SESSION_ID = 'BlUSkYymTt';
const IS_LOGIN_FOR_DOCTOR_APP = true;
diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart
index c31788f9..10f97042 100644
--- a/lib/config/localized_values.dart
+++ b/lib/config/localized_values.dart
@@ -254,6 +254,7 @@ const Map> localizedValues = {
"beingBad": {"en": "being bad", "ar": "سيء"},
"beingGreat": {"en": "being great", "ar": "رائع"},
"cancel": {"en": "CANCEL", "ar": "الغاء"},
+ "cancelSmall": {"en": "Cancel", "ar": "الغاء"},
"ok": {"en": "OK", "ar": "موافق"},
"done": {"en": "DONE", "ar": "تأكيد"},
"resumecall": {"en": "Resume call", "ar": "استئناف المكالمة"},
@@ -484,6 +485,7 @@ const Map> localizedValues = {
"ar": "ملاحظات على نوع النظام الغذائي"
},
"save": {"en": "SAVE", "ar": "حفظ"},
+ "saveSmall": {"en": "Save", "ar": "حفظ"},
"postPlansEstimatedCost": {
"en": "POST PLANS & ESTIMATED COST",
"ar": "خطط ما بعد العملية والتكلفة المقدرة"
@@ -677,6 +679,7 @@ const Map> localizedValues = {
"progressNoteSOAP": {"en": "Progress Note", "ar": "ملاحظة التقدم"},
"addProgressNote": {"en": "Add Progress Note", "ar": "أضف ملاحظة التقدم"},
"createdBy": {"en": "Created By :", "ar": "أضيفت عن طريق: "},
+ "createdOn": {"en": "Created On :", "ar": "تم إنشاؤه في: "},
"riskScore": {"en": "Risk Score :", "ar": "درجة المخاطر"},
"editedBy": {"en": "Edited By :", "ar": "عدلت من : "},
"currentMedications": {"en": "Current Medications", "ar": "الأدوية الحالية"},
@@ -1160,7 +1163,73 @@ const Map> localizedValues = {
"afterOrderCreation": {"en": "After order created, you cannot modify the principal diagnosis, Do you want to continue?", "ar":"بعد إنشاء الطلب، لا يمكنك تعديل التشخيص الأساسي، هل تريد المتابعة؟"},
"principalCoveredOrNot": {"en": "Principal Diagnosis is not covered for this patient", "ar":"لا يتم تغطية التشخيص الرئيسي لهذا المريض"},
"complexDiagnosis": {"en": "Complex Diagnosis", "ar":"التشخيص المعقد"},
+ "noComplaintsFound": {"en": "No Chief Complaints added, please add it from the button above", "ar":"لم تتم إضافة شكاوى رئيسية ، يرجى إضافتها من الزر أعلاه"},
+ "noKnownAllergies": {"en": "No Known Allergies", "ar":"لا يوجد حساسية معروفة"},
+ "addChiefComplaint": {"en": "Add Chief Complaints*", "ar":"إضافة الشكاوى الرئيسية*"},
+ "myFavoriteList": {"en": "My Favourite List", "ar":"قائمتي المفضلة"},
+ "generalList": {"en": "General list", "ar":"قائمة عامة"},
+ "specialList": {"en": "Special List", "ar":"قائمة خاصة"},
+ "enterChiefCompliants": {"en": "Enter Chief Compliants", "ar":"أدخل رئيس الامتثال"},
+ "previousChiefCompaints": {"en": "Previous Chief Compaints", "ar":"رئيس الرسامين السابق"},
+ "listOfActiveEpisodes": {"en": "List of active episodes , select one to procedd", "ar":"قائمة الحلقات النشطة ، حدد واحدة لتقديمها"},
+ "select": {"en": "Select", "ar":"اختار"},
+ "resolve": {"en": "Resolve", "ar":"حسم"},
+ "audit": {"en": "Audit", "ar":"مراجعه الحسابات"},
+ "delete": {"en": "Delete", "ar":"حذف"},
+ "acute": {"en": "Acute", "ar":"شديد"},
+ "chronic": {"en": "Acute", "ar":"مزمن"},
+ "subAcute": {"en": "sub-acute", "ar":"شبه الحاد"},
+ "addDiagnosis": {"en": "Add Diagnosis", "ar":"إضافة تشخيص"},
+ "showAllDiagnosis": {"en": "Show all diagnosis", "ar":"عرض جميع التشخيصات"},
+ "makeCurrentDiagnosis": {"en": "Make Current Diagnosis", "ar":"جعل التشخيص الحالي"},
+ "mappedDiagnosis": {"en": "Mapped Diagnosis", "ar":"التشخيص المعين"},
+ "previousDiagnosis": {"en": "Previous Diagnosis", "ar":"التشخيص السابق"},
+ "addNewDiagnosis": {"en": "Add New Diagnosis", "ar":"إضافة تشخيص جديد"},
+ "currentDiagnosis": {"en": "Current Diagnosis", "ar":"التشخيص الحالي"},
+ "progressNoteType": {"en": "Progress Note Type", "ar":"نوع ملاحظة التقدم"},
+ "doctorProgressNote": {"en": "Doctor Progress Note", "ar":"مذكرة تقدم الطبيب"},
+ "addYourNote": {"en": "Add Your Note", "ar":"أضف ملاحظتك"},
+ "saveAsDraft": {"en": "Save As Draft", "ar":"حفظ كمسودة"},
+ "nurseNote": {"en": "Nurse Note", "ar":"ملاحظة الممرضة"},
+ "patientCondition": {"en": "Patient Condition", "ar":"حالة المريض"},
+ "examinationPart": {"en": "Examination Part", "ar":"جزء الامتحان"},
+ "historyOfIllness": {"en": "History of Present Illness*", "ar":"تاريخ المرض الحالي*"},
+ "historyTakenFrom": {"en": "History taken from", "ar":"التاريخ مأخوذ من"},
+ "familySpecify": {"en": "Family, Specify", "ar":"العائلة، حدد"},
+ "otherSpecify": {"en": "Other, Specify", "ar":"أخرى، حدد"},
+ "physicalExamination": {"en": "Physical Examination", "ar":"الفحص البدني"},
+ "addPhysicalExamination": {"en": "Add Physical Examination", "ar":"إضافة الفحص البدني"},
+ "noPhysicalExamination": {"en": "No Physical Examination added, please add it from the button above", "ar":"لم يتم إضافة فحص بدني ، يرجى إضافته من الزر أعلاه"},
+ "noProgressNote": {"en": "No Diagnosis added, please add it from the button above", "ar":"لم يتم إضافة تشخيص ، يرجى إضافته من الزر أعلاه"},
+ "mild": {"en": "Mild", "ar":"خفيف"},
+ "moderate": {"en": "Moderate", "ar":"معتدل"},
+ "remarksCanNotBeEmpty": {"en": "Remarks Can Not Be Empty", "ar":"لا يمكن أن تكون الملاحظات فارغة"},
+ "kindlySelectCategory": {"en": "Kindly Select Any Diagnosis Category", "ar":"يرجى اختيار أي فئة تشخيص"},
+ "noRemarks": {"en": "No Remarks", "ar":"لا ملاحظات"},
+ "event": {"en": "Event: ", "ar":"حدث: "},
+ "editDiagnosis": {"en": "Edit Diagnosis ", "ar":"تحرير التشخيص"},
+ "selectedDiagnosis": {"en": "Kindly Select Diagnosis", "ar":"يرجى اختيار التشخيص: "},
+ "selectConditionFirst": {"en": "Kindly Select Diagnosis Condition", "ar":"يرجى اختيار حالة التشخيص: "},
+ "deletedRemarks": {"en": "Deleted Remarks: ", "ar":"ملاحظات محذوفة: "},
+ "newValue": {"en": "New Value: ", "ar":"قيمة جديدة: "},
+ "fieldName": {"en": "Field Name: ", "ar":"اسم الحقل: "},
+ "noChangeRecorded": {"en": "No Change Recorded Unable To Perform Edit", "ar":"لم يتم تسجيل أي تغيير، غير قادر على إجراء التحرير"},
+ "oldValue": {"en": "Old Value: ", "ar":"القيمة القديمة: "},
+ "favoriteDiagnosis": {"en": "Favorite Diagnosis", "ar":"التشخيص المفضل"},
+ "addToFavorite": {"en": "Add To Favorite", "ar":"إضافة إلى المفضلة"},
+ "noDiagnosisFound": {"en": "No Diagnosis added, please add it from the button above", "ar":"لم يتم إضافة تشخيص ، يرجى إضافته من الزر أعلاه"},
+ "areYouSureYouWantToDeleteDiagnosis": {
+ "en": "Are you sure you want to delete diagnosis",
+ "ar": "هل أنت متأكد من أنك تريد حذف التشخيص"
+ },
+ "activate": {"en": "Activate", "ar":"فعل"},
+ "stable": {"en": "Stable", "ar":"مستقر"},
+ "resolved": {"en": "Resolved", "ar":"تم الحل"},
+ "diagnosisAlreadyDeleted": {"en": "Diagnosis Already Deleted", "ar":"تم حذف التشخيص بالفعل"},
+ "diagnosisAlreadyResolved": {"en": "Diagnosis Already Resolved", "ar":"تم حل التشخيص بالفعل"},
+ "selectReaction": {"en": "Select Reaction", "ar":"حدد رد الفعل"},
+ "progressNoteCanNotBeEmpty": {"en": "Progress Note Can Not Be Empty", "ar":"ملاحظة التقدم لا يمكن أن تكون فارغة"},
};
diff --git a/lib/core/model/SOAP/allergy/get_allergies_list_vida_plus.dart b/lib/core/model/SOAP/allergy/get_allergies_list_vida_plus.dart
new file mode 100644
index 00000000..09a4d3cc
--- /dev/null
+++ b/lib/core/model/SOAP/allergy/get_allergies_list_vida_plus.dart
@@ -0,0 +1,130 @@
+class AllergiesListVidaPlus {
+ int? allergyID;
+ String? allergyName;
+ List? allergyReactionDTOs;
+ int? allergyRevisionID;
+ String? allergyTypeCode;
+ int? allergyTypeID;
+ String? allergyTypeName;
+ int? hospitalGroupID;
+ int? hospitalID;
+ bool? isActive;
+ bool? isSnowMedAllergy;
+ String? snowMedCode;
+ String? remark;
+ AllergiesListVidaPlus(
+ {this.allergyID,
+ this.allergyName,
+ this.allergyReactionDTOs,
+ this.allergyRevisionID,
+ this.allergyTypeCode,
+ this.allergyTypeID,
+ this.allergyTypeName,
+ this.hospitalGroupID,
+ this.hospitalID,
+ this.isActive,
+ this.isSnowMedAllergy,
+ this.snowMedCode,
+ this.remark
+ });
+
+ AllergiesListVidaPlus.fromJson(Map json) {
+ allergyID = json['allergyID'];
+ allergyName = json['allergyName'];
+ if (json['allergyReactionDTOs'] != null) {
+ allergyReactionDTOs = [];
+ json['allergyReactionDTOs'].forEach((v) {
+ allergyReactionDTOs!.add(new AllergyReactionDTOs.fromJson(v));
+ });
+ }
+ allergyRevisionID = json['allergyRevisionID'];
+ allergyTypeCode = json['allergyTypeCode'];
+ allergyTypeID = json['allergyTypeID'];
+ allergyTypeName = json['allergyTypeName'];
+ hospitalGroupID = json['hospitalGroupID'];
+ hospitalID = json['hospitalID'];
+ isActive = json['isActive'];
+ isSnowMedAllergy = json['isSnowMedAllergy'];
+ snowMedCode = json['snowMedCode'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['allergyID'] = this.allergyID;
+ data['allergyName'] = this.allergyName;
+ if (this.allergyReactionDTOs != null) {
+ data['allergyReactionDTOs'] =
+ this.allergyReactionDTOs!.map((v) => v.toJson()).toList();
+ }
+ data['allergyRevisionID'] = this.allergyRevisionID;
+ data['allergyTypeCode'] = this.allergyTypeCode;
+ data['allergyTypeID'] = this.allergyTypeID;
+ data['allergyTypeName'] = this.allergyTypeName;
+ data['hospitalGroupID'] = this.hospitalGroupID;
+ data['hospitalID'] = this.hospitalID;
+ data['isActive'] = this.isActive;
+ data['isSnowMedAllergy'] = this.isSnowMedAllergy;
+ data['snowMedCode'] = this.snowMedCode;
+ return data;
+ }
+}
+
+class AllergyReactionDTOs {
+ int? allergyReactionID;
+ String? allergyReactionName;
+ int? allergyReactionRevisionID;
+ dynamic? hospitalGroupID;
+ int? hospitalID;
+ bool? isActive;
+ bool? isSelected =false;
+ int? dbCRUDOperation =1;
+ int? pomrid;
+ int? patientID;
+ int? allergyReactionMappingID = 0;
+ int? severity =1;
+ AllergyReactionDTOs(
+ {this.allergyReactionID,
+ this.allergyReactionName,
+ this.allergyReactionRevisionID,
+ this.hospitalGroupID,
+ this.hospitalID,
+ this.isActive,
+ this.isSelected,
+ this.dbCRUDOperation,
+ this.pomrid,
+ this.patientID,
+ this.allergyReactionMappingID,
+ this.severity =1
+ });
+
+ AllergyReactionDTOs.fromJson(Map json) {
+ allergyReactionID = json['allergyReactionID'];
+ allergyReactionName = json['allergyReactionName'];
+ allergyReactionRevisionID = json['allergyReactionRevisionID'];
+ hospitalGroupID = json['hospitalGroupID'];
+ hospitalID = json['hospitalID'];
+ isActive = json['isActive'];
+ dbCRUDOperation = json["DbCRUDOperation"];
+ pomrid = json['pomrid'];
+ patientID = json['patientID'];
+ allergyReactionMappingID = json['allergyReactionMappingID'];
+ severity = json['severity'];
+
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['allergyReactionID'] = this.allergyReactionID;
+ data['allergyReactionName'] = this.allergyReactionName;
+ data['allergyReactionRevisionID'] = this.allergyReactionRevisionID;
+ data['hospitalGroupID'] = this.hospitalGroupID;
+ data['hospitalID'] = this.hospitalID;
+ data['isActive'] = this.isActive;
+ data["DbCRUDOperation"] = this.dbCRUDOperation;
+ data['pomrid'] = this.pomrid;
+ data['patientID'] = patientID;
+ data['allergyReactionMappingID'] = this.allergyReactionMappingID;
+ data['severity'] = this.severity;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/allergy/get_patient_allergies_list_vida_plus.dart b/lib/core/model/SOAP/allergy/get_patient_allergies_list_vida_plus.dart
new file mode 100644
index 00000000..ce84f58b
--- /dev/null
+++ b/lib/core/model/SOAP/allergy/get_patient_allergies_list_vida_plus.dart
@@ -0,0 +1,128 @@
+class PatientAllergiesVidaPlus {
+ int? allergyID;
+ String? allergyName;
+ int? allergyTypeID;
+ String? allergyTypeName;
+ int? hospitalGroupID;
+ int? hospitalID;
+ bool? isActivePatientsAllergy;
+ int? patientID;
+ List? patientsAllergyReactionsDTOs;
+ int? patientsAllergyRevisionID;
+ int? pomrID;
+ String? remark;
+
+ PatientAllergiesVidaPlus(
+ {this.allergyID,
+ this.allergyName,
+ this.allergyTypeID,
+ this.allergyTypeName,
+ this.hospitalGroupID,
+ this.hospitalID,
+ this.isActivePatientsAllergy,
+ this.patientID,
+ this.patientsAllergyReactionsDTOs,
+ this.patientsAllergyRevisionID,
+ this.pomrID,
+ this.remark});
+
+ PatientAllergiesVidaPlus.fromJson(Map json) {
+ allergyID = json['allergyID'];
+ allergyName = json['allergyName'];
+ allergyTypeID = json['allergyTypeID'];
+ allergyTypeName = json['allergyTypeName'];
+ hospitalGroupID = json['hospitalGroupID'];
+ hospitalID = json['hospitalID'];
+ isActivePatientsAllergy = json['isActivePatientsAllergy'];
+ patientID = json['patientID'];
+ if (json['patientsAllergyReactionsDTOs'] != null) {
+ patientsAllergyReactionsDTOs = [];
+ json['patientsAllergyReactionsDTOs'].forEach((v) {
+ patientsAllergyReactionsDTOs!
+ .add(new PatientsAllergyReactionsDTOs.fromJson(v));
+ });
+ }
+ patientsAllergyRevisionID = json['patientsAllergyRevisionID'];
+ pomrID = json['pomrID'];
+ remark = json['remark'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['allergyID'] = this.allergyID;
+ data['allergyName'] = this.allergyName;
+ data['allergyTypeID'] = this.allergyTypeID;
+ data['allergyTypeName'] = this.allergyTypeName;
+ data['hospitalGroupID'] = this.hospitalGroupID;
+ data['hospitalID'] = this.hospitalID;
+ data['isActivePatientsAllergy'] = this.isActivePatientsAllergy;
+ data['patientID'] = this.patientID;
+ if (this.patientsAllergyReactionsDTOs != null) {
+ data['patientsAllergyReactionsDTOs'] =
+ this.patientsAllergyReactionsDTOs!.map((v) => v.toJson()).toList();
+ }
+ data['patientsAllergyRevisionID'] = this.patientsAllergyRevisionID;
+ data['pomrID'] = this.pomrID;
+ data['remark'] = this.remark;
+ return data;
+ }
+}
+
+class PatientsAllergyReactionsDTOs {
+ int? allergyReactionID;
+ int? allergyReactionMappingID;
+ String? allergyReactionName;
+ int? hospitalGroupID;
+ int? hospitalID;
+ bool? isActive;
+ int? patientID;
+ int? patientsAllergyReactionRevisionID;
+ int? pomrId;
+ int? severity =1;
+ bool? isSelected =true;
+ String? reactionSelection ="";
+ PatientsAllergyReactionsDTOs(
+ {this.allergyReactionID,
+ this.allergyReactionMappingID,
+ this.allergyReactionName,
+ this.hospitalGroupID,
+ this.hospitalID,
+ this.isActive,
+ this.patientID,
+ this.patientsAllergyReactionRevisionID,
+ this.pomrId,
+ this.severity =1,
+ this.isSelected,
+ this.reactionSelection
+ });
+
+ PatientsAllergyReactionsDTOs.fromJson(Map json) {
+ allergyReactionID = json['allergyReactionID'];
+ allergyReactionMappingID = json['allergyReactionMappingID'];
+ allergyReactionName = json['allergyReactionName'];
+ hospitalGroupID = json['hospitalGroupID'];
+ hospitalID = json['hospitalID'];
+ isActive = json['isActive'];
+ patientID = json['patientID'];
+ patientsAllergyReactionRevisionID =
+ json['patientsAllergyReactionRevisionID'];
+ pomrId = json['pomrId'];
+ severity = json['severity'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['allergyReactionID'] = this.allergyReactionID;
+ data['allergyReactionMappingID'] = this.allergyReactionMappingID;
+ data['allergyReactionName'] = this.allergyReactionName;
+ data['hospitalGroupID'] = this.hospitalGroupID;
+ data['hospitalID'] = this.hospitalID;
+ data['isActive'] = this.isActive;
+ data['patientID'] = this.patientID;
+ data['patientsAllergyReactionRevisionID'] =
+ this.patientsAllergyReactionRevisionID;
+ data['pomrId'] = this.pomrId;
+ data['severity'] = this.severity;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/assessment/FavoriteDiseaseDetails.dart b/lib/core/model/SOAP/assessment/FavoriteDiseaseDetails.dart
new file mode 100644
index 00000000..19614800
--- /dev/null
+++ b/lib/core/model/SOAP/assessment/FavoriteDiseaseDetails.dart
@@ -0,0 +1,92 @@
+class FavoriteDiseaseDetails {
+ String? categoryCode;
+ int? categoryId;
+ String? chapterCode;
+ String? codeRange;
+ String? createdBy;
+ String? diseaseType;
+ String? diseases;
+ String? diseasesCode;
+ int? diseasesId;
+ int? favoritesId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ int? icdId;
+ String? icdSubVersion;
+ String? icdType;
+ String? icdVersion;
+ bool? isDeleted;
+ String? parentDiseasesCode;
+ String? problemCode;
+ String? problemDescription;
+ int? problemMasterId;
+ int? problemMasterRevisionId;
+ String? problemName;
+ String? problemType;
+ String? rowVersion;
+ String? sectionCode;
+ int? specificationId;
+
+ FavoriteDiseaseDetails.fromJson(Map json) {
+ categoryCode = json['CategoryCode'];
+ categoryId = json['CategoryId'];
+ chapterCode = json['ChapterCode'];
+ codeRange = json['CodeRange'];
+ createdBy = json['CreatedBy'];
+ diseaseType = json['DiseaseType'];
+ diseases = json['Diseases'];
+ diseasesCode = json['DiseasesCode'];
+ diseasesId = json['DiseasesId'];
+ favoritesId = json['FavoritesId'];
+ hospitalGroupId = json['HospitalGroupID'];
+ hospitalId = json['HospitalID'];
+ icdId = json['IcdId'];
+ icdSubVersion = json['IcdSubVersion'];
+ icdType = json['IcdType'];
+ icdVersion = json['IcdVersion'];
+ isDeleted = json['IsDeleted'];
+ parentDiseasesCode = json['ParentDiseasesCode'];
+ problemCode = json['ProblemCode'];
+ problemDescription = json['ProblemDescription'];
+ problemMasterId = json['ProblemMasterID'];
+ problemMasterRevisionId = json['ProblemMasterRevisionID'];
+ problemName = json['ProblemName'];
+ problemType = json['ProblemType'];
+ rowVersion = json['RowVersion'];
+ sectionCode = json['SectionCode'];
+ specificationId = json['SpecificationId'];
+ }
+
+ // toJson method
+ Map toJson() {
+ return {
+ 'CategoryCode': categoryCode,
+ 'CategoryId': categoryId,
+ 'ChapterCode': chapterCode,
+ 'CodeRange': codeRange,
+ 'CreatedBy': createdBy,
+ 'DiseaseType': diseaseType,
+ 'Diseases': diseases,
+ 'DiseasesCode': diseasesCode,
+ 'DiseasesId': diseasesId,
+ 'FavoritesId': favoritesId,
+ 'HospitalGroupID': hospitalGroupId,
+ 'HospitalID': hospitalId,
+ 'IcdId': icdId,
+ 'IcdSubVersion': icdSubVersion,
+ 'IcdType': icdType,
+ 'IcdVersion': icdVersion,
+ 'IsDeleted': isDeleted,
+ 'ParentDiseasesCode': parentDiseasesCode,
+ 'ProblemCode': problemCode,
+ 'ProblemDescription': problemDescription,
+ 'ProblemMasterID': problemMasterId,
+ 'ProblemMasterRevisionID': problemMasterRevisionId,
+ 'ProblemName': problemName,
+ 'ProblemType': problemType,
+ 'RowVersion': rowVersion,
+ 'SectionCode': sectionCode,
+ 'SpecificationId': specificationId,
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/assessment/audit_diagnosis.dart b/lib/core/model/SOAP/assessment/audit_diagnosis.dart
new file mode 100644
index 00000000..f98205dc
--- /dev/null
+++ b/lib/core/model/SOAP/assessment/audit_diagnosis.dart
@@ -0,0 +1,39 @@
+class AuditDiagnosis {
+ String? approvedBy;
+ String? approvedOn;
+ String? createdBy;
+ String? createdOn;
+ String? deletedBy;
+ String? deletedOn;
+ String? deletedRemarks;
+ String? doctorName;
+ String? diagnosisType;
+ bool? isEventIdentifiedExternally;
+ bool? isResolved;
+ String? modifiedBy;
+ String? modifiedOn;
+ int? patientId;
+ int? patientProblemRevisionId;
+ String? remarks;
+ String? status;
+
+ AuditDiagnosis.fromJson(Map json) {
+ approvedBy = json['approvedBy'];
+ approvedOn = json['approvedOn'];
+ createdBy = json['createdBy'];
+ createdOn = json['createdOn'];
+ deletedBy = json['deletedBy'];
+ deletedOn = json['deletedOn'];
+ doctorName = json['doctorName'];
+ deletedRemarks = json['deletedRemarks'];
+ diagnosisType = json['diagnosisType'];
+ isEventIdentifiedExternally = json['isEventIdentifiedExternally'];
+ isResolved = json['isResolved'];
+ modifiedBy = json['modifiedBy'];
+ modifiedOn = json['modifiedOn'];
+ patientId = json['patientId'];
+ patientProblemRevisionId = json['patientProblemRevisionId'];
+ remarks = json['remarks'];
+ status = json['status'];
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/assessment/diagnosis_type.dart b/lib/core/model/SOAP/assessment/diagnosis_type.dart
new file mode 100644
index 00000000..549342d0
--- /dev/null
+++ b/lib/core/model/SOAP/assessment/diagnosis_type.dart
@@ -0,0 +1,10 @@
+class DiagnosisType {
+ String? diagnosisType;
+ String? name;
+
+
+ DiagnosisType.fromJson(Map json) {
+ diagnosisType = json['diagnosisType'] ?? '';
+ name = json['name'] ?? '';
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/assessment/patient_previous_diagnosis.dart b/lib/core/model/SOAP/assessment/patient_previous_diagnosis.dart
new file mode 100644
index 00000000..99a50bf6
--- /dev/null
+++ b/lib/core/model/SOAP/assessment/patient_previous_diagnosis.dart
@@ -0,0 +1,287 @@
+class PatientPreviousDiagnosis {
+ bool? active;
+ int? admissionId;
+ int? admissionRequestId;
+ int? appointmentId;
+ String? approvedBy;
+ String? approvedOn;
+ int? assessmentId;
+ int? chiefComplainId;
+ int? clinicGroupId;
+ int? clinicId;
+ String? condition;
+ String? createdBy;
+ String? createdOn;
+ String? deletedBy;
+ String? deletedByDoctorName;
+ String? deletedOn;
+ String? deletedRemarks;
+ String? diagnosisType;
+ int? doctorId;
+ int? episodeId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ dynamic icdCodeDetailsDto;
+ String? icdSubVersion;
+ String? icdType;
+ dynamic icdVersion;
+ String? location;
+ String? loginUserId;
+ String? modifiedBy;
+ String? modifiedOn;
+ String? module;
+ String? parentLocation;
+ int? patientId;
+ dynamic patientProblemChangeHistories;
+ int? patientProblemId;
+ int? patientProblemRevisionId;
+ int? pomrId;
+ bool? previousProblem;
+ int? problemId;
+ String? problemName;
+ String? remarks;
+ bool? resolved;
+ String? selectedCategoryCode;
+ String? selectedChapterCode;
+ String? selectedDisease;
+ String? selectedIcdCode;
+ String? selectedSectionCode;
+ String? status;
+ List? visitWisePatientDiagnoses;
+ bool? visitWiseSelected;
+
+ PatientPreviousDiagnosis.fromJson(Map json) {
+ active = json['active'];
+ admissionId = json['admissionId'];
+ admissionRequestId = json['admissionRequestId'];
+ appointmentId = json['appointmentId'];
+ approvedBy = json['approvedBy'];
+ approvedOn = json['approvedOn'];
+ assessmentId = json['assessmentId'];
+ chiefComplainId = json['chiefComplainId'];
+ clinicGroupId = json['clinicGroupId'];
+ clinicId = json['clinicId'];
+ condition = json['condition'];
+ createdBy = json['createdBy'];
+ createdOn = json['createdOn'];
+ deletedBy = json['deletedBy'];
+ deletedByDoctorName = json['deletedByDoctorName'];
+ deletedOn = json['deletedOn'];
+ deletedRemarks = json['deletedRemarks'];
+ diagnosisType = json['diagnosisType'];
+ doctorId = json['doctorId'];
+ episodeId = json['episodeId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ icdCodeDetailsDto = json['icdCodeDetailsDto'];
+ icdSubVersion = json['icdSubVersion'];
+ icdType = json['icdType'];
+ icdVersion = json['icdVersion'];
+ location = json['location'];
+ loginUserId = json['loginUserId'];
+ modifiedBy = json['modifiedBy'];
+ modifiedOn = json['modifiedOn'];
+ module = json['module'];
+ parentLocation = json['parentLocation'];
+ patientId = json['patientId'];
+ patientProblemChangeHistories = json['patientProblemChangeHistories'];
+ patientProblemId = json['patientProblemId'];
+ patientProblemRevisionId = json['patientProblemRevisionId'];
+ pomrId = json['pomrId'];
+ previousProblem = json['previousProblem'];
+ problemId = json['problemId'];
+ problemName = json['problemName'];
+ remarks = json['remarks'];
+ resolved = json['resolved'];
+ selectedCategoryCode = json['selectedCategoryCode'];
+ selectedChapterCode = json['selectedChapterCode'];
+ selectedDisease = json['selectedDisease'];
+ selectedIcdCode = json['selectedIcdCode'];
+ selectedSectionCode = json['selectedSectionCode'];
+ status = json['status'];
+ visitWiseSelected = json['visitWiseSelected'];
+ if (json['visitWisePatientDiagnoses'] != null) {
+ visitWisePatientDiagnoses = [];
+ json['visitWisePatientDiagnoses'].forEach((v) {
+ visitWisePatientDiagnoses!.add(VisitWisePatientDiagnosis.fromJson(v));
+ });
+ }
+ }
+
+ Map toJson() {
+ return {
+ 'active': active,
+ 'admissionId': admissionId ?? 0,
+ 'admissionRequestId': admissionRequestId ?? 0,
+ 'appointmentId': appointmentId ?? 0,
+ 'approvedBy': approvedBy,
+ 'approvedOn': approvedOn,
+ 'assessmentId': assessmentId ?? 0,
+ 'chiefComplainId': chiefComplainId ?? 0,
+ 'clinicGroupId': clinicGroupId ?? 0,
+ 'clinicId': clinicId,
+ 'condition': condition,
+ 'createdBy': createdBy,
+ 'createdOn': createdOn,
+ 'deletedBy': deletedBy,
+ 'deletedByDoctorName': deletedByDoctorName,
+ 'deletedOn': deletedOn,
+ 'deletedRemarks': deletedRemarks,
+ 'diagnosisType': diagnosisType,
+ 'doctorId': doctorId,
+ 'episodeId': episodeId ?? 0,
+ 'hospitalGroupId': hospitalGroupId,
+ 'hospitalId': hospitalId,
+ 'icdCodeDetailsDto': icdCodeDetailsDto,
+ 'icdSubVersion': icdSubVersion,
+ 'icdType': icdType,
+ 'icdVersion': icdVersion,
+ 'location': location,
+ 'loginUserId': loginUserId,
+ 'modifiedBy': modifiedBy,
+ 'modifiedOn': modifiedOn,
+ 'module': module,
+ 'parentLocation': parentLocation,
+ 'patientId': patientId,
+ 'patientProblemChangeHistories': patientProblemChangeHistories,
+ 'patientProblemId': patientProblemId,
+ 'patientProblemRevisionId': patientProblemRevisionId,
+ 'pomrId': pomrId,
+ 'previousProblem': previousProblem,
+ 'problemId': problemId,
+ 'problemName': problemName,
+ 'remarks': remarks,
+ 'resolved': resolved,
+ 'selectedCategoryCode': selectedCategoryCode,
+ 'selectedChapterCode': selectedChapterCode,
+ 'selectedDisease': selectedDisease,
+ 'selectedIcdCode': selectedIcdCode,
+ 'selectedSectionCode': selectedSectionCode,
+ 'status': status,
+ 'visitWiseSelected': visitWiseSelected,
+ 'visitWisePatientDiagnoses': visitWisePatientDiagnoses?.map((v) => v.toJson()).toList(),
+ };
+ }
+}
+
+class VisitWisePatientDiagnosis {
+ bool? active;
+ int? admissionId;
+ int? appointmentId;
+ String? approvedBy;
+ String? approvedOn;
+ int? assessmentId;
+ int? clinicId;
+ String? condition;
+ String? createdBy;
+ String? createdOn;
+ String? deletedBy;
+ String? deletedOn;
+ String? deletedRemarks;
+ String? diagnosisType;
+ int? doctorId;
+ int? episodeId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? icdSubVersion;
+ String? icdType;
+ dynamic icdVersion;
+ bool? isPreviousProblem;
+ String? location;
+ String? loginUserId;
+ String? modifiedBy;
+ String? modifiedOn;
+ int? patientDiagnosisId;
+ int? patientId;
+ int? patientProblemRevisionId;
+ int? pomrId;
+ String? problemName;
+ String? remarks;
+ bool? resolved;
+ bool? selected;
+ String? selectedDisease;
+ int? selectedDoctorId;
+ String? selectedIcdCode;
+
+ VisitWisePatientDiagnosis.fromJson(Map json) {
+ active = json['active'];
+ admissionId = json['admissionId'];
+ appointmentId = json['appointmentId'];
+ approvedBy = json['approvedBy'];
+ approvedOn = json['approvedOn'];
+ assessmentId = json['assessmentId'];
+ clinicId = json['clinicId'];
+ condition = json['condition'];
+ createdBy = json['createdBy'];
+ createdOn = json['createdOn'];
+ deletedBy = json['deletedBy'];
+ deletedOn = json['deletedOn'];
+ deletedRemarks = json['deletedRemarks'];
+ diagnosisType = json['diagnosisType'];
+ doctorId = json['doctorId'];
+ episodeId = json['episodeId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ icdSubVersion = json['icdSubVersion'];
+ icdType = json['icdType'];
+ icdVersion = json['icdVersion'];
+ isPreviousProblem = json['isPreviousProblem'];
+ location = json['location'];
+ loginUserId = json['loginUserId'];
+ modifiedBy = json['modifiedBy'];
+ modifiedOn = json['modifiedOn'];
+ patientDiagnosisId = json['patientDiagnosisId'];
+ patientId = json['patientId'];
+ patientProblemRevisionId = json['patientProblemRevisionId'];
+ pomrId = json['pomrId'];
+ problemName = json['problemName'];
+ remarks = json['remarks'];
+ resolved = json['resolved'];
+ selected = json['selected'];
+ selectedDisease = json['selectedDisease'];
+ selectedDoctorId = json['selectedDoctorId'];
+ selectedIcdCode = json['selectedIcdCode'];
+ }
+
+ Map toJson() {
+ return {
+ 'active': active,
+ 'admissionId': admissionId,
+ 'appointmentId': appointmentId,
+ 'approvedBy': approvedBy,
+ 'approvedOn': approvedOn,
+ 'assessmentId': assessmentId,
+ 'clinicId': clinicId,
+ 'condition': condition,
+ 'createdBy': createdBy,
+ 'createdOn': createdOn,
+ 'deletedBy': deletedBy,
+ 'deletedOn': deletedOn,
+ 'deletedRemarks': deletedRemarks,
+ 'diagnosisType': diagnosisType,
+ 'doctorId': doctorId,
+ 'episodeId': episodeId,
+ 'hospitalGroupId': hospitalGroupId,
+ 'hospitalId': hospitalId,
+ 'icdSubVersion': icdSubVersion,
+ 'icdType': icdType,
+ 'icdVersion': icdVersion,
+ 'isPreviousProblem': isPreviousProblem,
+ 'location': location,
+ 'loginUserId': loginUserId,
+ 'modifiedBy': modifiedBy,
+ 'modifiedOn': modifiedOn,
+ 'patientDiagnosisId': patientDiagnosisId,
+ 'patientId': patientId,
+ 'patientProblemRevisionId': patientProblemRevisionId,
+ 'pomrId': pomrId,
+ 'problemName': problemName,
+ 'remarks': remarks,
+ 'resolved': resolved,
+ 'selected': selected,
+ 'selectedDisease': selectedDisease,
+ 'selectedDoctorId': selectedDoctorId,
+ 'selectedIcdCode': selectedIcdCode,
+ };
+ }
+}
diff --git a/lib/core/model/SOAP/assessment/search_diagnosis.dart b/lib/core/model/SOAP/assessment/search_diagnosis.dart
new file mode 100644
index 00000000..0a7ab2e7
--- /dev/null
+++ b/lib/core/model/SOAP/assessment/search_diagnosis.dart
@@ -0,0 +1,99 @@
+class SearchDiagnosis {
+ String? category;
+ String? categoryId;
+ String? codeRange;
+ String? diseaseType;
+ String? diseases;
+ String? diseasesBCode;
+ String? diseasesCode;
+ String? diseasesDataId;
+ String? diseasesId;
+ String? diseasesName;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? icdSubVersion;
+ String? icdType;
+ List? icdVersion;
+ String? icdVersionDisplay;
+ bool? isDeleted;
+ String? layerID;
+ String? parentDiseasesCode;
+ String? specification;
+ int? specificationId;
+ String? specificationNo;
+ String? selectedIcdCode;
+ String? selectedCategoryCode;
+ String? selectedSectionCode;
+ String? selectedChapterCode;
+ String? selectedNandaCode;
+ bool isFavorite = false;
+
+ // Default constructor
+ SearchDiagnosis();
+
+ // fromJson constructor
+ SearchDiagnosis.fromJson(Map json) {
+ category = json['category'];
+ categoryId = json['categoryId'];
+ codeRange = json['codeRange'];
+ diseaseType = json['diseaseType'];
+ diseases = json['diseases'];
+ diseasesBCode = json['diseasesBCode'];
+ diseasesCode = json['diseasesCode'];
+ diseasesDataId = json['diseasesDataId'];
+ diseasesId = json['diseasesId'];
+ diseasesName = json['diseasesName'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ icdSubVersion = json['icdSubVersion'];
+ icdType = json['icdType'];
+ icdVersion = json['icdVersion'] != null
+ ? List.from(json['icdVersion'])
+ : null;
+ icdVersionDisplay = json['icdVersionDisplay'];
+ isDeleted = json['isDeleted'] == "True";
+ layerID = json['layerID'];
+ parentDiseasesCode = json['parentDiseasesCode'];
+ specification = json['specification'];
+ specificationId = json['specificationId'];
+ specificationNo = json['specificationNo'];
+ selectedIcdCode = json['selectedIcdCode'];
+ selectedCategoryCode = json['selectedCategoryCode'];
+ selectedSectionCode = json['selectedSectionCode'];
+ selectedChapterCode = json['selectedChapterCode'];
+ selectedNandaCode = json['selectedNandaCode'];
+ }
+
+ // toJson method
+ Map toJson() {
+ return {
+ 'category': category,
+ 'categoryId': categoryId,
+ 'codeRange': codeRange,
+ 'diseaseType': diseaseType,
+ 'diseases': diseases,
+ 'diseasesBCode': diseasesBCode,
+ 'diseasesCode': diseasesCode,
+ 'diseasesDataId': diseasesDataId,
+ 'diseasesId': diseasesId,
+ 'diseasesName': diseasesName,
+ 'hospitalGroupId': hospitalGroupId,
+ 'hospitalId': hospitalId,
+ 'icdSubVersion': icdSubVersion,
+ 'icdType': icdType,
+ 'icdVersion': icdVersion,
+ 'icdVersionDisplay': icdVersionDisplay,
+ 'isDeleted': isDeleted.toString(),
+ 'layerID': layerID,
+ 'parentDiseasesCode': parentDiseasesCode,
+ 'specification': specification,
+ 'specificationId': specificationId,
+ 'specificationNo': specificationNo,
+ 'selectedIcdCode': selectedIcdCode,
+ 'selectedCategoryCode': selectedCategoryCode,
+ 'selectedSectionCode': selectedSectionCode,
+ 'selectedChapterCode': selectedChapterCode,
+ 'selectedNandaCode': selectedNandaCode,
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/chief_complaint/episode_by_chief_complaint_vidaplus.dart b/lib/core/model/SOAP/chief_complaint/episode_by_chief_complaint_vidaplus.dart
new file mode 100644
index 00000000..13005c9e
--- /dev/null
+++ b/lib/core/model/SOAP/chief_complaint/episode_by_chief_complaint_vidaplus.dart
@@ -0,0 +1,249 @@
+class EpisodeByChiefComplaintVidaPlus {
+ int? clinicId;
+ String? createdOn;
+ int? doctorId;
+ int? episodeStatus;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? modifiedOn;
+ int? patientEpisodeId;
+ int? patientId;
+ List? patientPomrs;
+
+ EpisodeByChiefComplaintVidaPlus(
+ {this.clinicId,
+ this.createdOn,
+ this.doctorId,
+ this.episodeStatus,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.modifiedOn,
+ this.patientEpisodeId,
+ this.patientId,
+ this.patientPomrs});
+
+ EpisodeByChiefComplaintVidaPlus.fromJson(Map json) {
+ clinicId = json['clinicId'];
+ createdOn = json['createdOn'];
+ doctorId = json['doctorId'];
+ episodeStatus = json['episodeStatus'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ modifiedOn = json['modifiedOn'];
+ patientEpisodeId = json['patientEpisodeId'];
+ patientId = json['patientId'];
+ if (json['patientPomrs'] != null) {
+ patientPomrs = [];
+ json['patientPomrs'].forEach((v) {
+ patientPomrs!.add(new PatientPomrs.fromJson(v));
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['clinicId'] = this.clinicId;
+ data['createdOn'] = this.createdOn;
+ data['doctorId'] = this.doctorId;
+ data['episodeStatus'] = this.episodeStatus;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['modifiedOn'] = this.modifiedOn;
+ data['patientEpisodeId'] = this.patientEpisodeId;
+ data['patientId'] = this.patientId;
+ if (this.patientPomrs != null) {
+ data['patientPomrs'] = this.patientPomrs!.map((v) => v.toJson()).toList();
+ }
+ return data;
+ }
+}
+
+class PatientPomrs {
+ int? appointmentId;
+ int? chiefComplainTemplateId;
+ List? chiefComplains;
+ int? clinicGroupId;
+ String? createdOn;
+ int? doctorId;
+ String? doctorName;
+ int? episodeId;
+ bool? fallowUp;
+ bool? fallowUpRequired;
+ bool? isReadOnly;
+ String? modifiedOn;
+ int? patientId;
+ int? patientPomrId;
+ String? pomrSingOn;
+ int? pomrStatus;
+ bool? readOnly;
+ String? seenAtStatus;
+ String? vprnSeenAtStatus;
+
+ PatientPomrs(
+ {this.appointmentId,
+ this.chiefComplainTemplateId,
+ this.chiefComplains,
+ this.clinicGroupId,
+ this.createdOn,
+ this.doctorId,
+ this.doctorName,
+ this.episodeId,
+ this.fallowUp,
+ this.fallowUpRequired,
+ this.isReadOnly,
+ this.modifiedOn,
+ this.patientId,
+ this.patientPomrId,
+ this.pomrSingOn,
+ this.pomrStatus,
+ this.readOnly,
+ this.seenAtStatus,
+ this.vprnSeenAtStatus});
+
+ PatientPomrs.fromJson(Map json) {
+ appointmentId = json['appointmentId'];
+ chiefComplainTemplateId = json['chiefComplainTemplateId'];
+ if (json['chiefComplains'] != null) {
+ chiefComplains = [];
+ json['chiefComplains'].forEach((v) {
+ chiefComplains!.add(new ChiefComplains.fromJson(v));
+ });
+ }
+ clinicGroupId = json['clinicGroupId'];
+ createdOn = json['createdOn'];
+ doctorId = json['doctorId'];
+ doctorName = json['doctorName'];
+ episodeId = json['episodeId'];
+ fallowUp = json['fallowUp'];
+ fallowUpRequired = json['fallowUpRequired'];
+ isReadOnly = json['isReadOnly'];
+ modifiedOn = json['modifiedOn'];
+ patientId = json['patientId'];
+ patientPomrId = json['patientPomrId'];
+ pomrSingOn = json['pomrSingOn'];
+ pomrStatus = json['pomrStatus'];
+ readOnly = json['readOnly'];
+ seenAtStatus = json['seenAtStatus'];
+ vprnSeenAtStatus = json['vprnSeenAtStatus'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['appointmentId'] = this.appointmentId;
+ data['chiefComplainTemplateId'] = this.chiefComplainTemplateId;
+ if (this.chiefComplains != null) {
+ data['chiefComplains'] =
+ this.chiefComplains!.map((v) => v.toJson()).toList();
+ }
+ data['clinicGroupId'] = this.clinicGroupId;
+ data['createdOn'] = this.createdOn;
+ data['doctorId'] = this.doctorId;
+ data['doctorName'] = this.doctorName;
+ data['episodeId'] = this.episodeId;
+ data['fallowUp'] = this.fallowUp;
+ data['fallowUpRequired'] = this.fallowUpRequired;
+ data['isReadOnly'] = this.isReadOnly;
+ data['modifiedOn'] = this.modifiedOn;
+ data['patientId'] = this.patientId;
+ data['patientPomrId'] = this.patientPomrId;
+ data['pomrSingOn'] = this.pomrSingOn;
+ data['pomrStatus'] = this.pomrStatus;
+ data['readOnly'] = this.readOnly;
+ data['seenAtStatus'] = this.seenAtStatus;
+ data['vprnSeenAtStatus'] = this.vprnSeenAtStatus;
+ return data;
+ }
+}
+
+class ChiefComplains {
+ int? appointmentId;
+ String? chiefComplain;
+ int? chiefComplainId;
+ int? clinicId;
+ String? createdBy;
+ int? createdId;
+ String? createdOn;
+ int? doctorId;
+ String? doctorName;
+ int? episodeId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? loginUserId;
+ String? modifiedBy;
+ Null? modifiedId;
+ String? modifiedOn;
+ int? patientId;
+ String? patientName;
+ int? patientPomrId;
+ int? chiefComplainTemplateId;
+
+
+ ChiefComplains(
+ {this.appointmentId,
+ this.chiefComplain,
+ this.chiefComplainId,
+ this.clinicId,
+ this.createdBy,
+ this.createdId,
+ this.createdOn,
+ this.doctorId,
+ this.doctorName,
+ this.episodeId,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.loginUserId,
+ this.modifiedBy,
+ this.modifiedId,
+ this.modifiedOn,
+ this.patientId,
+ this.patientName,
+ this.patientPomrId});
+
+ ChiefComplains.fromJson(Map json) {
+ appointmentId = json['appointmentId'];
+ chiefComplain = json['chiefComplain'];
+ chiefComplainTemplateId = json['chiefComplainTemplateId'];
+ chiefComplainId = json['chiefComplainId'];
+ clinicId = json['clinicId'];
+ createdBy = json['createdBy'];
+ createdId = json['createdId'];
+ createdOn = json['createdOn'];
+ doctorId = json['doctorId'];
+ doctorName = json['doctorName'];
+ episodeId = json['episodeId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ loginUserId = json['loginUserId'];
+ modifiedBy = json['modifiedBy'];
+ modifiedId = json['modifiedId'];
+ modifiedOn = json['modifiedOn'];
+ patientId = json['patientId'];
+ patientName = json['patientName'];
+ patientPomrId = json['patientPomrId'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['appointmentId'] = this.appointmentId;
+ data['chiefComplain'] = this.chiefComplain;
+ data['chiefComplainId'] = this.chiefComplainId;
+ data['clinicId'] = this.clinicId;
+ data['createdBy'] = this.createdBy;
+ data['createdId'] = this.createdId;
+ data['createdOn'] = this.createdOn;
+ data['doctorId'] = this.doctorId;
+ data['doctorName'] = this.doctorName;
+ data['episodeId'] = this.episodeId;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['loginUserId'] = this.loginUserId;
+ data['modifiedBy'] = this.modifiedBy;
+ data['chiefComplainTemplateId'] = this.chiefComplainTemplateId;
+ data['modifiedId'] = this.modifiedId;
+ data['modifiedOn'] = this.modifiedOn;
+ data['patientId'] = this.patientId;
+ data['patientName'] = this.patientName;
+ data['patientPomrId'] = this.patientPomrId;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/chief_complaint/get_chief_complaint_vida_plus.dart b/lib/core/model/SOAP/chief_complaint/get_chief_complaint_vida_plus.dart
new file mode 100644
index 00000000..cf2c5f7b
--- /dev/null
+++ b/lib/core/model/SOAP/chief_complaint/get_chief_complaint_vida_plus.dart
@@ -0,0 +1,68 @@
+class GetChiefComplaintVidaPlus {
+ int? appointmentId;
+ String? chiefComplain;
+ int? chiefComplainId;
+ int? chiefComplainTemplateId;
+ int? clinicGroupId;
+ int? clinicId;
+ int? doctorId;
+ String? doctorName;
+ int? episodeId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? loginUserId;
+ int? patientId;
+ int? patientPomrId;
+
+ GetChiefComplaintVidaPlus(
+ {this.appointmentId,
+ this.chiefComplain,
+ this.chiefComplainId,
+ this.chiefComplainTemplateId,
+ this.clinicGroupId,
+ this.clinicId,
+ this.doctorId,
+ this.doctorName,
+ this.episodeId,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.loginUserId,
+ this.patientId,
+ this.patientPomrId});
+
+ GetChiefComplaintVidaPlus.fromJson(Map json) {
+ appointmentId = json['appointmentId'];
+ chiefComplain = json['chiefComplain'];
+ chiefComplainId = json['chiefComplainId'];
+ chiefComplainTemplateId = json['chiefComplainTemplateId'];
+ clinicGroupId = json['clinicGroupId'];
+ clinicId = json['clinicId'];
+ doctorId = json['doctorId'];
+ doctorName = json['doctorName'];
+ episodeId = json['episodeId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ loginUserId = json['loginUserId'];
+ patientId = json['patientId'];
+ patientPomrId = json['patientPomrId'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['appointmentId'] = this.appointmentId;
+ data['chiefComplain'] = this.chiefComplain;
+ data['chiefComplainId'] = this.chiefComplainId;
+ data['chiefComplainTemplateId'] = this.chiefComplainTemplateId;
+ data['clinicGroupId'] = this.clinicGroupId;
+ data['clinicId'] = this.clinicId;
+ data['doctorId'] = this.doctorId;
+ data['doctorName'] = this.doctorName;
+ data['episodeId'] = this.episodeId;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['loginUserId'] = this.loginUserId;
+ data['patientId'] = this.patientId;
+ data['patientPomrId'] = this.patientPomrId;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/chief_complaint/search_chief_complaint_vidaplus.dart b/lib/core/model/SOAP/chief_complaint/search_chief_complaint_vidaplus.dart
new file mode 100644
index 00000000..389cd99f
--- /dev/null
+++ b/lib/core/model/SOAP/chief_complaint/search_chief_complaint_vidaplus.dart
@@ -0,0 +1,40 @@
+class SearchChiefComplaint {
+ String? chiefComplain;
+ String? chiefComplainCode;
+ int? chiefComplainId;
+ String? clinic;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? nursingGroup;
+
+ SearchChiefComplaint(
+ {this.chiefComplain,
+ this.chiefComplainCode,
+ this.chiefComplainId,
+ this.clinic,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.nursingGroup});
+
+ SearchChiefComplaint.fromJson(Map json) {
+ chiefComplain = json['chiefComplain'];
+ chiefComplainCode = json['chiefComplainCode'];
+ chiefComplainId = json['chiefComplainId'];
+ clinic = json['clinic'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ nursingGroup = json['nursingGroup'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['chiefComplain'] = this.chiefComplain;
+ data['chiefComplainCode'] = this.chiefComplainCode;
+ data['chiefComplainId'] = this.chiefComplainId;
+ data['clinic'] = this.clinic;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['nursingGroup'] = this.nursingGroup;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/get_hopi_details.dart b/lib/core/model/SOAP/get_hopi_details.dart
new file mode 100644
index 00000000..eadf19ba
--- /dev/null
+++ b/lib/core/model/SOAP/get_hopi_details.dart
@@ -0,0 +1,66 @@
+class GetHopiDetails {
+ int? clinicId;
+ int? doctorId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? hpi;
+ int? hpiId;
+ bool? isHpiTakenFamily;
+ bool? isHpiTakenOther;
+ bool? isHpiTakenPatient;
+ String? hpiTakenFamilyText;
+ String? hpiTakenOtherText;
+ String? loginUserId;
+ int? patientId;
+ int? patientPomrId;
+
+ GetHopiDetails(
+ {this.clinicId,
+ this.doctorId,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.hpi,
+ this.hpiId,
+ this.isHpiTakenFamily,
+ this.isHpiTakenOther,
+ this.isHpiTakenPatient,
+ this.loginUserId,
+ this.patientId,
+ this.patientPomrId});
+
+ GetHopiDetails.fromJson(Map json) {
+ clinicId = json['clinicId'];
+ doctorId = json['doctorId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ hpi = json['hpi'];
+ hpiId = json['hpiId'];
+ isHpiTakenFamily = json['isHpiTakenFamily'];
+ isHpiTakenOther = json['isHpiTakenOther'];
+ isHpiTakenPatient = json['isHpiTakenPatient'];
+ loginUserId = json['loginUserId'];
+ patientId = json['patientId'];
+ patientPomrId = json['patientPomrId'];
+ hpiTakenFamilyText = json['hpiTakenFamilyText'];
+ hpiTakenOtherText = json['hpiTakenOtherText'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['clinicId'] = this.clinicId;
+ data['doctorId'] = this.doctorId;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['hpi'] = this.hpi;
+ data['hpiId'] = this.hpiId;
+ data['isHpiTakenFamily'] = this.isHpiTakenFamily;
+ data['isHpiTakenOther'] = this.isHpiTakenOther;
+ data['isHpiTakenPatient'] = this.isHpiTakenPatient;
+ data['loginUserId'] = this.loginUserId;
+ data['patientId'] = this.patientId;
+ data['patientPomrId'] = this.patientPomrId;
+ data['hpiTakenFamilyText'] = this.hpiTakenFamilyText;
+ data['hpiTakenOtherText'] = this.hpiTakenOtherText;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/home_medication_vp/GetHomeMedication.dart b/lib/core/model/SOAP/home_medication_vp/GetHomeMedication.dart
new file mode 100644
index 00000000..01d186c3
--- /dev/null
+++ b/lib/core/model/SOAP/home_medication_vp/GetHomeMedication.dart
@@ -0,0 +1,156 @@
+class GetHomeMedicationList {
+ List? personalizationEntity;
+ int? appointmentId;
+ int? clinicGroupId;
+ int? clinicId;
+ String? createdTime;
+ String? doseQuantity;
+ String? formularyName;
+ String? frequencyId;
+ String? frequencyString;
+ String? genericFormularyId;
+ String? homeMedFrom;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? id;
+ bool? isActive;
+ bool? isEHRIPReconciled;
+ bool? isEHROPReconciled;
+ bool? isERIPReconciled;
+ bool? isFreeText;
+ bool? isReconciled;
+ bool? isUnknownDetail;
+ String? lastUpdatedTime;
+ int? patientId;
+ int? patientPomrId;
+ String? prescribeTypeAlias;
+ int? prescribedItemId;
+ String? prescribedItemName;
+ String? remarks;
+ String? routeId;
+ String? routeString;
+ String? rowVersion;
+ String? sentence;
+ String? strengthId;
+ String? strengthString;
+
+ GetHomeMedicationList(
+ {this.personalizationEntity,
+ this.appointmentId,
+ this.clinicGroupId,
+ this.clinicId,
+ this.createdTime,
+ this.doseQuantity,
+ this.formularyName,
+ this.frequencyId,
+ this.frequencyString,
+ this.genericFormularyId,
+ this.homeMedFrom,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.id,
+ this.isActive,
+ this.isEHRIPReconciled,
+ this.isEHROPReconciled,
+ this.isERIPReconciled,
+ this.isFreeText,
+ this.isReconciled,
+ this.isUnknownDetail,
+ this.lastUpdatedTime,
+ this.patientId,
+ this.patientPomrId,
+ this.prescribeTypeAlias,
+ this.prescribedItemId,
+ this.prescribedItemName,
+ this.remarks,
+ this.routeId,
+ this.routeString,
+ this.rowVersion,
+ this.sentence,
+ this.strengthId,
+ this.strengthString});
+
+ GetHomeMedicationList.fromJson(Map json) {
+ if (json['PersonalizationEntity'] != null) {
+ personalizationEntity = [];
+ json['PersonalizationEntity'].forEach((v) {
+ personalizationEntity!.add( v.fromJson(v));
+ });
+ }
+ appointmentId = json['appointmentId'];
+ clinicGroupId = json['clinicGroupId'];
+ clinicId = json['clinicId'];
+ createdTime = json['createdTime'];
+ doseQuantity = json['doseQuantity'];
+ formularyName = json['formularyName'];
+ frequencyId = json['frequencyId'];
+ frequencyString = json['frequencyString'];
+ genericFormularyId = json['genericFormularyId'];
+ homeMedFrom = json['homeMedFrom'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ id = json['id'];
+ isActive = json['isActive'];
+ isEHRIPReconciled = json['isEHRIPReconciled'];
+ isEHROPReconciled = json['isEHROPReconciled'];
+ isERIPReconciled = json['isERIPReconciled'];
+ isFreeText = json['isFreeText'];
+ isReconciled = json['isReconciled'];
+ isUnknownDetail = json['isUnknownDetail'];
+ lastUpdatedTime = json['lastUpdatedTime'];
+ patientId = json['patientId'];
+ patientPomrId = json['patientPomrId'];
+ prescribeTypeAlias = json['prescribeTypeAlias'];
+ prescribedItemId = json['prescribedItemId'];
+ prescribedItemName = json['prescribedItemName'];
+ remarks = json['remarks'];
+ routeId = json['routeId'];
+ routeString = json['routeString'];
+ rowVersion = json['rowVersion'];
+ sentence = json['sentence'];
+ strengthId = json['strengthId'];
+ strengthString = json['strengthString'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ if (this.personalizationEntity != null) {
+ data['PersonalizationEntity'] =
+ this.personalizationEntity!.map((v) => v.toJson()).toList();
+ }
+ data['appointmentId'] = this.appointmentId;
+ data['clinicGroupId'] = this.clinicGroupId;
+ data['clinicId'] = this.clinicId;
+ data['createdTime'] = this.createdTime;
+ data['doseQuantity'] = this.doseQuantity;
+ data['formularyName'] = this.formularyName;
+ data['frequencyId'] = this.frequencyId;
+ data['frequencyString'] = this.frequencyString;
+ data['genericFormularyId'] = this.genericFormularyId;
+ data['homeMedFrom'] = this.homeMedFrom;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['id'] = this.id;
+ data['isActive'] = this.isActive;
+ data['isEHRIPReconciled'] = this.isEHRIPReconciled;
+ data['isEHROPReconciled'] = this.isEHROPReconciled;
+ data['isERIPReconciled'] = this.isERIPReconciled;
+ data['isFreeText'] = this.isFreeText;
+ data['isReconciled'] = this.isReconciled;
+ data['isUnknownDetail'] = this.isUnknownDetail;
+ data['lastUpdatedTime'] = this.lastUpdatedTime;
+ data['patientId'] = this.patientId;
+ data['patientPomrId'] = this.patientPomrId;
+ data['prescribeTypeAlias'] = this.prescribeTypeAlias;
+ data['prescribedItemId'] = this.prescribedItemId;
+ data['prescribedItemName'] = this.prescribedItemName;
+ data['remarks'] = this.remarks;
+ data['routeId'] = this.routeId;
+ data['routeString'] = this.routeString;
+ data['rowVersion'] = this.rowVersion;
+ data['sentence'] = this.sentence;
+ data['strengthId'] = this.strengthId;
+ data['strengthString'] = this.strengthString;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedication.dart b/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedication.dart
new file mode 100644
index 00000000..fd94d9cf
--- /dev/null
+++ b/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedication.dart
@@ -0,0 +1,40 @@
+class GetSearchCurrentMedication {
+ String? formularyName;
+ String? genericFormularyCode;
+ String? genericFormularyId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? itemType;
+ bool? outOfStock;
+
+ GetSearchCurrentMedication(
+ {this.formularyName,
+ this.genericFormularyCode,
+ this.genericFormularyId,
+ this.hospitalGroupId,
+ this.hospitalId,
+ this.itemType,
+ this.outOfStock});
+
+ GetSearchCurrentMedication.fromJson(Map json) {
+ formularyName = json['formularyName'];
+ genericFormularyCode = json['genericFormularyCode'];
+ genericFormularyId = json['genericFormularyId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ itemType = json['itemType'];
+ outOfStock = json['outOfStock'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ data['formularyName'] = this.formularyName;
+ data['genericFormularyCode'] = this.genericFormularyCode;
+ data['genericFormularyId'] = this.genericFormularyId;
+ data['hospitalGroupId'] = this.hospitalGroupId;
+ data['hospitalId'] = this.hospitalId;
+ data['itemType'] = this.itemType;
+ data['outOfStock'] = this.outOfStock;
+ return data;
+ }
+}
diff --git a/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedicationDetails.dart b/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedicationDetails.dart
new file mode 100644
index 00000000..0cdd9ada
--- /dev/null
+++ b/lib/core/model/SOAP/home_medication_vp/GetSearchCurrentMedicationDetails.dart
@@ -0,0 +1,108 @@
+class GetSearchCurrentMedicationDetails {
+ List? genericItemFrequencyDetailsEntity;
+ List? genericItemRouteDetailsEntity;
+ List? itemStrengthDetailsDto;
+ int? patientTypeId;
+
+ GetSearchCurrentMedicationDetails({this.genericItemFrequencyDetailsEntity, this.genericItemRouteDetailsEntity, this.itemStrengthDetailsDto, this.patientTypeId});
+
+ GetSearchCurrentMedicationDetails.fromJson(Map json) {
+ if (json['genericItemFrequencyDetailsEntity'] != null) {
+ genericItemFrequencyDetailsEntity = [];
+ json['genericItemFrequencyDetailsEntity'].forEach((v) { genericItemFrequencyDetailsEntity!.add(new GenericItemFrequencyDetailsEntity.fromJson(v)); });
+ }
+ if (json['genericItemRouteDetailsEntity'] != null) {
+ genericItemRouteDetailsEntity = [];
+ json['genericItemRouteDetailsEntity'].forEach((v) { genericItemRouteDetailsEntity!.add(new GenericItemRouteDetailsEntity.fromJson(v)); });
+ }
+ if (json['itemStrengthDetailsDto'] != null) {
+ itemStrengthDetailsDto = [];
+ json['itemStrengthDetailsDto'].forEach((v) { itemStrengthDetailsDto!.add(new ItemStrengthDetailsDto.fromJson(v)); });
+ }
+ patientTypeId = json['patientTypeId'];
+ }
+
+ Map toJson() {
+ final Map data = new Map();
+ if (this.genericItemFrequencyDetailsEntity != null) {
+ data['genericItemFrequencyDetailsEntity'] = this.genericItemFrequencyDetailsEntity!.map((v) => v.toJson()).toList();
+ }
+ if (this.genericItemRouteDetailsEntity != null) {
+ data['genericItemRouteDetailsEntity'] = this.genericItemRouteDetailsEntity!.map((v) => v.toJson()).toList();
+ }
+ if (this.itemStrengthDetailsDto != null) {
+ data['itemStrengthDetailsDto'] = this.itemStrengthDetailsDto!.map((v) => v.toJson()).toList();
+ }
+ data['patientTypeId'] = this.patientTypeId;
+ return data;
+ }
+}
+
+class GenericItemFrequencyDetailsEntity {
+ bool? Default;
+ String? frequency;
+ int? frequencyId;
+ int? interval;
+
+ GenericItemFrequencyDetailsEntity({this.Default, this.frequency, this.frequencyId, this.interval});
+
+GenericItemFrequencyDetailsEntity.fromJson(Map json) {
+Default = json['Default'];
+frequency = json['Frequency'];
+frequencyId = json['FrequencyId'];
+interval = json['Interval'];
+}
+
+Map toJson() {
+final Map data = new Map();
+data['Default'] = this.Default;
+data['Frequency'] = this.frequency;
+data['FrequencyId'] = this.frequencyId;
+data['Interval'] = this.interval;
+return data;
+}
+}
+
+class GenericItemRouteDetailsEntity {
+bool? Default;
+String? route;
+int? routeId;
+
+GenericItemRouteDetailsEntity({this.Default, this.route, this.routeId});
+
+GenericItemRouteDetailsEntity.fromJson(Map json) {
+Default = json['default'];
+route = json['route'];
+routeId = json['routeId'];
+}
+
+Map toJson() {
+final Map data = new Map();
+data['default'] = this.Default;
+data['route'] = this.route;
+data['routeId'] = this.routeId;
+return data;
+}
+}
+
+class ItemStrengthDetailsDto {
+bool? Default;
+String? strength;
+int? strengthId;
+
+ItemStrengthDetailsDto({this.Default, this.strength, this.strengthId});
+
+ItemStrengthDetailsDto.fromJson(Map json) {
+Default = json['default'];
+strength = json['strength'];
+strengthId = json['strengthId'];
+}
+
+Map toJson() {
+final Map data = new Map();
+data['default'] = this.Default;
+data['strength'] = this.strength;
+data['strengthId'] = this.strengthId;
+return data;
+}
+}
diff --git a/lib/core/model/SOAP/physical_exam/Category.dart b/lib/core/model/SOAP/physical_exam/Category.dart
new file mode 100644
index 00000000..26542d27
--- /dev/null
+++ b/lib/core/model/SOAP/physical_exam/Category.dart
@@ -0,0 +1,96 @@
+import 'package:flutter/material.dart';
+
+class Condition {
+ String? conditionCode;
+ String? conditionName;
+
+ Condition();
+
+ Condition.fromJson(Map json) {
+ conditionCode = json['conditionCode'];
+ conditionName = json['conditionName'];
+ }
+
+ Map toJson() {
+ return {
+ 'conditionCode': conditionCode,
+ 'conditionName': conditionName,
+ };
+ }
+}
+
+class Category {
+ int? categoryId;
+ String? code;
+ String? codeAlias;
+ List? conditionsList;
+ String? description;
+ String? descriptionAlias;
+ int? id;
+ bool? isActive;
+ bool? isBuiltin;
+ String? languageCode;
+ String? name;
+ String? nameAlias;
+ int? rowVersion;
+ int? specialityId;
+ String? specialityName;
+ List? translationValues;
+ bool isSelected = false;
+ TextEditingController remarksController = TextEditingController();
+ int selectedCondition = -1;
+ String selectedConditionName = "";
+ String? pomrId;
+ int? paitientId;
+ int? userID;
+ bool isExpanded = false;
+
+ Category();
+
+ Category.fromJson(Map json,int? specialityId, String specialityName, String? pomrId, int paitientId, int userID) {
+ categoryId = json['categoryId'];
+ code = json['code'];
+ codeAlias = json['codeAlias'];
+ if (json['conditionsList'] != null) {
+ conditionsList = [];
+ json['conditionsList'].forEach((v) {
+ conditionsList!.add(Condition.fromJson(v));
+ });
+ }
+ if(conditionsList?.isNotEmpty == true) selectedCondition = int.parse(conditionsList?.first.conditionName ??'-1');
+ description = json['description'];
+ descriptionAlias = json['descriptionAlias'];
+ id = json['id'];
+ isActive = json['isActive'];
+ isBuiltin = json['isBuiltin'];
+ languageCode = json['languageCode'];
+ name = json['name'];
+ nameAlias = json['nameAlias'];
+ rowVersion = json['rowVersion'];
+ translationValues = json['translationValues'];
+ this.specialityName = specialityName;
+ this.specialityId = specialityId;
+ this.pomrId = pomrId;
+ this.paitientId = paitientId;
+ this.userID = userID;
+ }
+
+ Map toJson() {
+ return {
+ 'categoryId': categoryId,
+ 'code': code,
+ 'codeAlias': codeAlias,
+ 'conditionsList': conditionsList?.map((v) => v.toJson()).toList(),
+ 'description': description,
+ 'descriptionAlias': descriptionAlias,
+ 'id': id,
+ 'isActive': isActive,
+ 'isBuiltin': isBuiltin,
+ 'languageCode': languageCode,
+ 'name': name,
+ 'nameAlias': nameAlias,
+ 'rowVersion': rowVersion,
+ 'translationValues': translationValues,
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/physical_exam/CreatePhysicalExamination.dart b/lib/core/model/SOAP/physical_exam/CreatePhysicalExamination.dart
new file mode 100644
index 00000000..7a60cd06
--- /dev/null
+++ b/lib/core/model/SOAP/physical_exam/CreatePhysicalExamination.dart
@@ -0,0 +1,74 @@
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/Category.dart';
+
+class CreatePhysicalExamination {
+ bool? isChecked; // it will be told
+ bool? selected; // same as above
+ String? pomrid; // paitient
+ int? patientID; // paitint
+ bool? isClinicPhysicalExamination; // it will be told
+ dynamic? physicalExaminationSystemID; // category id
+ String? physicalExaminationDescription; // name of the category
+ int? specialityID; // id of the specialitiy id
+ dynamic selectedOptions; // it will also be told but it could be sent as null
+ bool? isMandatory; // it will also be checked default value is false
+ String? specialityDescription; // name of the speciality
+ int? physicalExaminationCondition; // condition selected
+ String? loginUserId; // doctor id
+ String? remark;
+
+ CreatePhysicalExamination();
+
+ CreatePhysicalExamination.fromJson(Map json) {
+ isChecked = json['isChecked'];
+ selected = json['selected'];
+ pomrid = json['pomrid'];
+ patientID = json['patientID'];
+ isClinicPhysicalExamination = json['isClinicPhysicalExamination'];
+ physicalExaminationSystemID = json['physicalExaminationSystemID'];
+ physicalExaminationDescription = json['physicalExaminationDescription'];
+ specialityID = json['specialityID'];
+ selectedOptions = json['selectedOptions'];
+ isMandatory = json['isMandatory'];
+ specialityDescription = json['specialityDescription'];
+ physicalExaminationCondition = json['physicalExaminationCondition'];
+ loginUserId = json['loginUserId'];
+ remark = json['remark'];
+ }
+
+ Map toJson() {
+ return {
+ 'isChecked': isChecked,
+ 'selected': selected,
+ 'pomrid': pomrid,
+ 'patientID': patientID,
+ 'isClinicPhysicalExamination': isClinicPhysicalExamination,
+ 'physicalExaminationSystemID': physicalExaminationSystemID,
+ 'physicalExaminationDescription': physicalExaminationDescription,
+ 'specialityID': specialityID,
+ 'selectedOptions': selectedOptions,
+ 'isMandatory': isMandatory,
+ 'specialityDescription': specialityDescription,
+ 'physicalExaminationCondition': physicalExaminationCondition,
+ 'loginUserId': loginUserId,
+ 'remark': remark,
+ };
+ }
+}
+
+extension ConvertCategoryToCreatePhysicalExamination on Category {
+ CreatePhysicalExamination createPhysicalExaminationFromCategory() =>
+ CreatePhysicalExamination()
+ ..isChecked = true
+ ..physicalExaminationDescription = this.name
+ ..physicalExaminationSystemID = this.id
+ ..physicalExaminationCondition = this.selectedCondition
+ ..remark = this.remarksController.text
+ ..selected = false
+ ..specialityID = this.specialityId
+ ..patientID = this.paitientId
+ ..pomrid = this.pomrId
+ ..loginUserId = this.userID?.toString()
+ ..isMandatory = false
+ ..specialityDescription = this.specialityName
+ ..isClinicPhysicalExamination = true;
+}
diff --git a/lib/core/model/SOAP/physical_exam/GeneralSpeciality.dart b/lib/core/model/SOAP/physical_exam/GeneralSpeciality.dart
new file mode 100644
index 00000000..7428f6a2
--- /dev/null
+++ b/lib/core/model/SOAP/physical_exam/GeneralSpeciality.dart
@@ -0,0 +1,24 @@
+class GeneralSpeciality {
+ int? id;
+ bool? isActive;
+ String? name;
+ int? rowVersion;
+ bool isSelected = false;
+
+ GeneralSpeciality();
+
+ GeneralSpeciality.fromJson(Map json) {
+ id = json['id'];
+ isActive = json['isActive'];
+ name = json['name'];
+ rowVersion = json['rowVersion'];
+ }
+ Map toJson() {
+ return {
+ 'id': id,
+ 'isActive': isActive,
+ 'name': name,
+ 'rowVersion': rowVersion,
+ };
+ }
+}
diff --git a/lib/core/model/SOAP/physical_exam/patient_physical_examination.dart b/lib/core/model/SOAP/physical_exam/patient_physical_examination.dart
new file mode 100644
index 00000000..ec4253a6
--- /dev/null
+++ b/lib/core/model/SOAP/physical_exam/patient_physical_examination.dart
@@ -0,0 +1,97 @@
+class PatientPhysicalExamination {
+ int? patientPhysicalExaminationRevisionID;
+ int? patientPhysicalExaminationID;
+ int? patientID;
+ int? physicalExaminationSystemID;
+ String? physicalExaminationDescription;
+ int? physicalExaminationCondition;
+ String? remark;
+ int? assessmentId;
+ String? userType;
+ int? specialtyID;
+ String? specialityDescription;
+ String? loginUserId;
+ bool? isMandatory;
+ String? examinationType;
+ dynamic additionalParams; // Use dynamic for null or varied types
+ int? hospitalGroupID;
+ int? hospitalID;
+ int? dbCRUDOperation;
+ bool? isActive;
+ int? createdBy;
+ String? createdOn;
+ int? modifiedBy;
+ String? modifiedOn;
+ int? approvedBy;
+ String? approvedOn;
+ String? rowVersion;
+ String? pomrid;
+
+ // Default constructor
+ PatientPhysicalExamination();
+
+ // fromJson constructor
+ PatientPhysicalExamination.fromJson(Map json) {
+ patientPhysicalExaminationRevisionID =
+ json['patientPhysicalExaminationRevisionID'];
+ patientPhysicalExaminationID = json['patientPhysicalExaminationID'];
+ patientID = json['patientID'];
+ physicalExaminationSystemID = json['physicalExaminationSystemID'];
+ physicalExaminationDescription = json['physicalExaminationDescription'];
+ physicalExaminationCondition = json['physicalExaminationCondition'];
+ remark = json['remark'];
+ assessmentId = json['assessmentId'];
+ userType = json['userType'];
+ specialtyID = json['specialtyID'];
+ specialityDescription = json['specialityDescription'];
+ loginUserId = json['loginUserId'];
+ isMandatory = json['isMandatory'];
+ examinationType = json['examinationType'];
+ additionalParams = json['additionalParams'];
+ hospitalGroupID = json['hospitalGroupID'];
+ hospitalID = json['hospitalID'];
+ dbCRUDOperation = json['dbCRUDOperation'];
+ isActive = json['isActive'];
+ createdBy = json['createdBy'];
+ createdOn = json['createdOn'];
+ modifiedBy = json['modifiedBy'];
+ modifiedOn = json['modifiedOn'];
+ approvedBy = json['approvedBy'];
+ approvedOn = json['approvedOn'];
+ rowVersion = json['rowVersion'];
+ pomrid = json['pomrid'];
+ }
+
+ // toJson method
+ Map toJson() {
+ return {
+ 'patientPhysicalExaminationRevisionID': patientPhysicalExaminationRevisionID,
+ 'patientPhysicalExaminationID': patientPhysicalExaminationID,
+ 'patientID': patientID,
+ 'physicalExaminationSystemID': physicalExaminationSystemID,
+ 'physicalExaminationDescription': physicalExaminationDescription,
+ 'physicalExaminationCondition': physicalExaminationCondition,
+ 'remark': remark,
+ 'assessmentId': assessmentId,
+ 'userType': userType,
+ 'specialtyID': specialtyID,
+ 'specialityDescription': specialityDescription,
+ 'loginUserId': loginUserId,
+ 'isMandatory': isMandatory,
+ 'examinationType': examinationType,
+ 'additionalParams': additionalParams,
+ 'hospitalGroupID': hospitalGroupID,
+ 'hospitalID': hospitalID,
+ 'dbCRUDOperation': dbCRUDOperation,
+ 'isActive': isActive,
+ 'createdBy': createdBy,
+ 'createdOn': createdOn,
+ 'modifiedBy': modifiedBy,
+ 'modifiedOn': modifiedOn,
+ 'approvedBy': approvedBy,
+ 'approvedOn': approvedOn,
+ 'rowVersion': rowVersion,
+ 'pomrid': pomrid,
+ };
+ }
+}
diff --git a/lib/core/model/SOAP/physical_exam/post_physical_examination_model.dart b/lib/core/model/SOAP/physical_exam/post_physical_examination_model.dart
new file mode 100644
index 00000000..026d8c54
--- /dev/null
+++ b/lib/core/model/SOAP/physical_exam/post_physical_examination_model.dart
@@ -0,0 +1,55 @@
+@deprecated
+class PostPhysicalExaminationModel {
+ bool? isChecked;
+ bool? selected;
+ int? pomrid;
+ int? patientID;
+ bool? isClinicPhysicalExamination;
+ int? physicalExaminationSystemID;
+ String? physicalExaminationDescription;
+ int? specialityID;
+ dynamic selectedOptions;
+ bool? isMandatory;
+ String? specialityDescription;
+ int? physicalExaminationCondition;
+ String? loginUserId;
+ String? remark;
+
+ PostPhysicalExaminationModel();
+
+ PostPhysicalExaminationModel.fromJson(Map json) {
+ isChecked = json['isChecked'];
+ selected = json['selected'];
+ pomrid = json['pomrid'];
+ patientID = json['patientID'];
+ isClinicPhysicalExamination = json['isClinicPhysicalExamination'];
+ physicalExaminationSystemID = json['physicalExaminationSystemID'];
+ physicalExaminationDescription = json['physicalExaminationDescription'];
+ specialityID = json['specialityID'];
+ selectedOptions = json['selectedOptions'];
+ isMandatory = json['isMandatory'];
+ specialityDescription = json['specialityDescription'];
+ physicalExaminationCondition = json['physicalExaminationCondition'];
+ loginUserId = json['loginUserId'];
+ remark = json['remark'];
+ }
+
+ Map toJson() {
+ return {
+ 'isChecked': isChecked,
+ 'selected': selected,
+ 'pomrid': pomrid,
+ 'patientID': patientID,
+ 'isClinicPhysicalExamination': isClinicPhysicalExamination,
+ 'physicalExaminationSystemID': physicalExaminationSystemID,
+ 'physicalExaminationDescription': physicalExaminationDescription,
+ 'specialityID': specialityID,
+ 'selectedOptions': selectedOptions,
+ 'isMandatory': isMandatory,
+ 'specialityDescription': specialityDescription,
+ 'physicalExaminationCondition': physicalExaminationCondition,
+ 'loginUserId': loginUserId,
+ 'remark': remark,
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/progress_note/Clinic.dart b/lib/core/model/SOAP/progress_note/Clinic.dart
new file mode 100644
index 00000000..2e452990
--- /dev/null
+++ b/lib/core/model/SOAP/progress_note/Clinic.dart
@@ -0,0 +1,35 @@
+class SOAPClinic {
+ int? clinicGroupID;
+ String? clinicGroupName;
+ int? clinicID;
+ String? clinicNameArabic;
+ String? clinicNameEnglish;
+
+ SOAPClinic({
+ this.clinicGroupID,
+ this.clinicGroupName,
+ this.clinicID,
+ this.clinicNameArabic,
+ this.clinicNameEnglish,
+ });
+
+ factory SOAPClinic.fromJson(Map json) {
+ return SOAPClinic(
+ clinicGroupID: json['clinicGroupID'],
+ clinicGroupName: json['clinicGroupName'],
+ clinicID: json['clinicID'],
+ clinicNameArabic: json['clinicNameArabic'],
+ clinicNameEnglish: json['clinicNameEnglish'],
+ );
+ }
+
+ Map toJson() {
+ return {
+ 'clinicGroupID': clinicGroupID,
+ 'clinicGroupName': clinicGroupName,
+ 'clinicID': clinicID,
+ 'clinicNameArabic': clinicNameArabic,
+ 'clinicNameEnglish': clinicNameEnglish,
+ };
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/progress_note/PatientCondition.dart b/lib/core/model/SOAP/progress_note/PatientCondition.dart
new file mode 100644
index 00000000..c082c501
--- /dev/null
+++ b/lib/core/model/SOAP/progress_note/PatientCondition.dart
@@ -0,0 +1,11 @@
+class PatientCondition{
+ String? code;
+ int? id;
+ String? name;
+
+ PatientCondition.fromJson(Map json){
+ name = json['name'] ?? '';
+ id = json['id'] ?? -1;
+ code = json['code'] ?? '';
+ }
+}
\ No newline at end of file
diff --git a/lib/core/model/SOAP/progress_note/progress_note.dart b/lib/core/model/SOAP/progress_note/progress_note.dart
new file mode 100644
index 00000000..3afc7be9
--- /dev/null
+++ b/lib/core/model/SOAP/progress_note/progress_note.dart
@@ -0,0 +1,85 @@
+class ProgressNote {
+ int? clinicGroupId;
+ int? clinicId;
+ int? createdById;
+ String? createdOn;
+ int? employeeId;
+ int? hospitalGroupId;
+ int? hospitalId;
+ String? loginUserId;
+ String? manualDate;
+ String? modifiedOn;
+ String? patientCondition;
+ String? patientConditionName;
+ int? patientId;
+ int? patientPomrId;
+ String? progressNote;
+ int? progressNoteId;
+ String? progressNotesTypes;
+ String? progressNotesTypesName;
+ String? speciality;
+ String? specialityName;
+ int? subCategoryId;
+ String? userFullName;
+ int? userId;
+ String? userType;
+
+ ProgressNote();
+
+ ProgressNote.fromJson(Map json) {
+ clinicGroupId = json['clinicGroupId'];
+ clinicId = json['clinicId'];
+ createdById = json['createdById'];
+ createdOn = json['createdOn'];
+ employeeId = json['employeeId'];
+ hospitalGroupId = json['hospitalGroupId'];
+ hospitalId = json['hospitalId'];
+ loginUserId = json['loginUserId'];
+ manualDate = json['manualDate'];
+ modifiedOn = json['modifiedOn'];
+ patientCondition = json['patientCondition'];
+ patientConditionName = json['patientConditionName'];
+ patientId = json['patientId'];
+ patientPomrId = json['patientPomrId'];
+ progressNote = json['progressNote'];
+ progressNoteId = json['progressNoteId'];
+ progressNotesTypes = json['progressNotesTypes'];
+ progressNotesTypesName = json['progressNotesTypesName'];
+ speciality = json['speciality'];
+ specialityName = json['specialityName'];
+ subCategoryId = json['subCategoryId'];
+ userFullName = json['userFullName'];
+ userId = json['userId'];
+ userType = json['userType'];
+ }
+
+ // toJson method
+ Map toJson() {
+ return {
+ 'clinicGroupId': clinicGroupId,
+ 'clinicId': clinicId,
+ 'createdById': createdById,
+ 'createdOn': createdOn,
+ 'employeeId': employeeId,
+ 'hospitalGroupId': hospitalGroupId,
+ 'hospitalId': hospitalId,
+ 'loginUserId': loginUserId,
+ 'manualDate': manualDate,
+ 'modifiedOn': modifiedOn,
+ 'patientCondition': patientCondition,
+ 'patientConditionName': patientConditionName,
+ 'patientId': patientId,
+ 'patientPomrId': patientPomrId,
+ 'progressNote': progressNote,
+ 'progressNoteId': progressNoteId,
+ 'progressNotesTypes': progressNotesTypes,
+ 'progressNotesTypesName': progressNotesTypesName,
+ 'speciality': speciality,
+ 'specialityName': specialityName,
+ 'subCategoryId': subCategoryId,
+ 'userFullName': userFullName,
+ 'userId': userId,
+ 'userType': userType,
+ };
+ }
+}
diff --git a/lib/core/model/diabetic_chart/GetDiabeticChartValuesResponseModel.dart b/lib/core/model/diabetic_chart/GetDiabeticChartValuesResponseModel.dart
index 1e5dd8fd..aa633671 100644
--- a/lib/core/model/diabetic_chart/GetDiabeticChartValuesResponseModel.dart
+++ b/lib/core/model/diabetic_chart/GetDiabeticChartValuesResponseModel.dart
@@ -2,7 +2,7 @@ class GetDiabeticChartValuesResponseModel {
String? resultType;
int? admissionNo;
String? dateChart;
- int? resultValue;
+ num? resultValue;
int? createdBy;
String? createdOn;
diff --git a/lib/core/model/patient/patiant_info_model.dart b/lib/core/model/patient/patiant_info_model.dart
index af04e752..4fb49f80 100644
--- a/lib/core/model/patient/patiant_info_model.dart
+++ b/lib/core/model/patient/patiant_info_model.dart
@@ -79,7 +79,7 @@ class PatiantInformtion {
int? status;
int? vcId;
String? voipToken;
-
+ String? pomrId;
PatiantInformtion(
{this.patientDetails,
this.projectId,
@@ -155,7 +155,9 @@ class PatiantInformtion {
this.vcId,
this.voipToken,
this.admissionDateWithDateTimeForm,
- this.appointmentDateWithDateTimeForm});
+ this.appointmentDateWithDateTimeForm,
+ this.pomrId
+ });
PatiantInformtion.fromJson(Map json) {
{
@@ -262,6 +264,7 @@ class PatiantInformtion {
consultationNotes = json['ConsultationNotes'];
patientStatus = json['PatientStatus'];
voipToken = json['VoipToken'];
+ pomrId = json['pomrId'];
admissionDateWithDateTimeForm = json["AdmissionDate"] != null
? AppDateUtils.convertStringToDate(json["AdmissionDate"])
: json["admissionDate"] != null
@@ -340,7 +343,7 @@ class PatiantInformtion {
data['ProjectID'] = this.projectId;
data['VC_ID'] = this.vcId;
data['VoipToken'] = this.voipToken;
-
+ data['pomrId'] = this.pomrId;
data["DateofBirth"] = this.dateofBirth;
data["dob"] = this.dateofBirth;
data['DateOfBirth'] = this.dateofBirth;
diff --git a/lib/core/model/radiology/final_radiology.dart b/lib/core/model/radiology/final_radiology.dart
index 7149ff2f..fde1b4a3 100644
--- a/lib/core/model/radiology/final_radiology.dart
+++ b/lib/core/model/radiology/final_radiology.dart
@@ -45,7 +45,7 @@ class FinalRadiology {
bool? isRadMedicalReport;
bool? isLiveCareAppodynamicment;
bool? isRecordFromVidaPlus;
- String? invoiceType;
+ dynamic invoiceType;
FinalRadiology(
{this.setupID,
@@ -105,7 +105,7 @@ class FinalRadiology {
doctorID = json['DoctorID'];
clinicID = json['ClinicID'];
orderDate = AppDateUtils.convertStringToDate(json['OrderDate']);
- reportDate = AppDateUtils.convertStringToDate(json['ReportDate']);
+ reportDate = AppDateUtils.convertStringToDate(json['ReadOn']);
reportData = json['ReportData'];
imageURL = json['ImageURL'];
procedureID = json['ProcedureID'];
@@ -141,7 +141,8 @@ class FinalRadiology {
isRadMedicalReport = json['isRadMedicalReport'];
isRecordFromVidaPlus = json['IsRecordFromVidaPlus'];
invoiceType = json["InvoiceType"];
- } catch (e) {
+ }
+ catch (e) {
print(e);
}
}
diff --git a/lib/core/service/authentication_service.dart b/lib/core/service/authentication_service.dart
index 303bcd79..2c0ab0d9 100644
--- a/lib/core/service/authentication_service.dart
+++ b/lib/core/service/authentication_service.dart
@@ -46,7 +46,7 @@ class AuthenticationService extends BaseService {
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
- }, body: {"IMEI": imei});
+ }, body: {"IMEI": imei, "TokenID": "@dm!n"});
} catch (error) {
hasError = true;
super.error = error.toString();
diff --git a/lib/core/service/base/lookup-service.dart b/lib/core/service/base/lookup-service.dart
index f1e086a1..b9f6a69f 100644
--- a/lib/core/service/base/lookup-service.dart
+++ b/lib/core/service/base/lookup-service.dart
@@ -214,4 +214,6 @@ class LookupService extends BaseService {
break;
}
}
+
+
}
diff --git a/lib/core/service/patient_medical_file/medical_report/PatientMedicalReportService.dart b/lib/core/service/patient_medical_file/medical_report/PatientMedicalReportService.dart
index e7626141..1adaae95 100644
--- a/lib/core/service/patient_medical_file/medical_report/PatientMedicalReportService.dart
+++ b/lib/core/service/patient_medical_file/medical_report/PatientMedicalReportService.dart
@@ -1,4 +1,5 @@
import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/core/model/doctor/doctor_profile_model.dart';
import 'package:doctor_app_flutter/core/service/base/base_service.dart';
import 'package:doctor_app_flutter/core/model/patient/MedicalReport/MedicalReportTemplate.dart';
import 'package:doctor_app_flutter/core/model/patient/MedicalReport/MeidcalReportModel.dart';
@@ -14,7 +15,7 @@ class PatientMedicalReportService extends BaseService {
await getDoctorProfile();
body['AdmissionNo'] = patient.admissionNo;
body['SetupID'] = doctorProfile!.setupID;
- body['ProjectID'] = doctorProfile!.projectID;
+ // body['ProjectID'] = doctorProfile!.projectID;
medicalReportList = [];
await baseAppClient.postPatient(PATIENT_MEDICAL_REPORT_GET_LIST, onSuccess: (dynamic response, int statusCode) {
if (response['DAPP_ListMedicalReportList'] != null) {
diff --git a/lib/core/service/patient_medical_file/soap/SOAP_service.dart b/lib/core/service/patient_medical_file/soap/SOAP_service.dart
index ab87eeb8..a1cfd751 100644
--- a/lib/core/service/patient_medical_file/soap/SOAP_service.dart
+++ b/lib/core/service/patient_medical_file/soap/SOAP_service.dart
@@ -1,8 +1,28 @@
import 'package:doctor_app_flutter/config/config.dart';
+import 'package:doctor_app_flutter/config/shared_pref_kay.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Allergy/get_allergies_res_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_res_model.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/allergy/get_allergies_list_vida_plus.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/allergy/get_patient_allergies_list_vida_plus.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/assessment/FavoriteDiseaseDetails.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/assessment/audit_diagnosis.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/assessment/patient_previous_diagnosis.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/assessment/search_diagnosis.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/assessment/patch_assessment_req_model.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/chief_complaint/episode_by_chief_complaint_vidaplus.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/chief_complaint/get_chief_complaint_vida_plus.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/chief_complaint/search_chief_complaint_vidaplus.dart';
import 'package:doctor_app_flutter/core/model/SOAP/general_get_req_for_SOAP.dart';
import 'package:doctor_app_flutter/core/model/SOAP/Assessment/get_assessment_req_model.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/get_hopi_details.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/Category.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/CreatePhysicalExamination.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/GeneralSpeciality.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/patient_physical_examination.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/post_physical_examination_model.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/home_medication_vp/GetHomeMedication.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/home_medication_vp/GetSearchCurrentMedication.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/home_medication_vp/GetSearchCurrentMedicationDetails.dart';
import 'package:doctor_app_flutter/core/model/SOAP/post_episode_req_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/chief_complaint/get_chief_complaint_req_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/chief_complaint/get_chief_complaint_res_model.dart';
@@ -17,10 +37,20 @@ import 'package:doctor_app_flutter/core/model/SOAP/history/post_histories_reques
import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/get_physical_exam_list_res_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/get_physical_exam_req_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/physical_exam/post_physical_exam_request_model.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/progress_note/Clinic.dart';
import 'package:doctor_app_flutter/core/model/SOAP/progress_note/GetGetProgressNoteResModel.dart';
+import 'package:doctor_app_flutter/core/model/SOAP/progress_note/PatientCondition.dart';
import 'package:doctor_app_flutter/core/model/SOAP/progress_note/get_progress_note_req_model.dart';
import 'package:doctor_app_flutter/core/model/SOAP/progress_note/post_progress_note_request_model.dart';
-
+import 'package:doctor_app_flutter/core/model/SOAP/progress_note/progress_note.dart';
+import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
+import 'package:doctor_app_flutter/core/service/base/lookup-service.dart';
+import 'package:doctor_app_flutter/utils/date-utils.dart';
+import 'package:doctor_app_flutter/utils/dr_app_toast_msg.dart';
+import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart';
+import 'package:doctor_app_flutter/utils/utils.dart';
+import '../../../../config/shared_pref_kay.dart';
+import '../../../../utils/date-utils.dart';
import '../../../model/SOAP/assessment/patch_assessment_req_model.dart';
import '../../../model/patient/patiant_info_model.dart';
import '../../base/lookup-service.dart';
@@ -31,10 +61,40 @@ class SOAPService extends LookupService {
List patientHistoryList = [];
List patientPhysicalExamList = [];
List patientProgressNoteList = [];
+ List patientProgressNoteListVidaPlus = [];
List patientAssessmentList = [];
+ List searchAllergiesList = [];
+ List patientAllergiesVidaPlus = [];
+ List hopiDetails = [];
+ List patientChiefComplaintListVidaPlus = [];
+ List searchChiefComplaintListVidaPlus = [];
+ List episodeByChiefComplaintListVidaPlus =
+ [];
+ List getHomeMedicationList = [];
+ List getSearchCurrentMedication = [];
+ List getSearchCurrentMedicationDetails =
+ [];
+ List patientPreviousDiagnosisList = [];
+ List patientDiagnosisList = [];
+ List favoriteDiagnosisDetailsList = [];
+ List auditDiagnosislist = [];
+ List searchDiagnosisList = [];
+ List patientPhysicalExaminationList = [];
+ List generalSpeciality = [];
+ List clinicsList = [];
+ List patientConditionList = [];
+ Map> specialityDetails = {};
+ Map patientConditionMap = {};
+ Map diagnosisTypeList = {};
+ Map diagnosisTypeTypeMapWithIdAsKey = {};
+ Map conditionTypeList = {};
+ Map conditionTypeMapWithIdAsKey = {};
+ List icdVersionList = [];
+ bool showAuditBottomSheet = false;
int? episodeID;
- bool isPrescriptionOrder =false;
+ bool isPrescriptionOrder = false;
+
Future postEpisode(PostEpisodeReqModel postEpisodeReqModel) async {
hasError = false;
@@ -318,22 +378,1224 @@ class SOAPService extends LookupService {
super.error = error;
}, body: getEpisodeForInpatientReqModel.toJson());
}
- Future isPrescriptionOrderCreated(
- PatiantInformtion patientInfo) async {
+
+ Future isPrescriptionOrderCreated(PatiantInformtion patientInfo) async {
hasError = false;
await baseAppClient.post(IS_PRESCRIPTION_ORDER_CREATED,
onSuccess: (dynamic response, int statusCode) {
- print("Success");
-
- isPrescriptionOrder = response['IsPrescriptionCreated'];
- }, onFailure: (String error, int statusCode) {
- hasError = true;
- super.error = error;
- }, body: {
- "PatientMRN":patientInfo.patientMRN,
- "EncounterNo":patientInfo.appointmentNo,
- "EncounterType":patientInfo.appointmentTypeId,
- "DoctorID":patientInfo.doctorId,
+ print("Success");
+
+ isPrescriptionOrder = response['IsPrescriptionCreated'];
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "PatientMRN": patientInfo.patientMRN,
+ "EncounterNo": patientInfo.appointmentNo,
+ "EncounterType": patientInfo.appointmentTypeId,
+ "DoctorID": patientInfo.doctorId,
+ });
+ }
+
+/* vida plus API allergies */
+
+ Future patientAllergies(PatiantInformtion patientInfo) async {
+ Map request = {
+ "patientId": patientInfo.patientMRN,
+ "ProjectID": patientInfo.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+ hasError = false;
+ await baseAppClient.post(PATIENT_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ print("Success");
+ patientAllergiesVidaPlus.clear();
+
+ response['List_PatientAllergies']['resultData'].forEach((v) {
+ patientAllergiesVidaPlus.add(PatientAllergiesVidaPlus.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ Future getEditAllergies(int allergyId) async {
+ hasError = false;
+
+ await baseAppClient.post(GET_EDIT_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ print("Success");
+ searchAllergiesList.clear();
+
+ response['List_SearchAllergies']['resultData'].forEach((v) {
+ searchAllergiesList.add(AllergiesListVidaPlus.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "allergyId": allergyId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ });
+ }
+
+ Future searchAllergies(String searchKey) async {
+ hasError = false;
+
+ await baseAppClient.post(SEARCH_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ print("Success");
+ searchAllergiesList.clear();
+
+ response['List_SearchAllergies']['resultData'].forEach((v) {
+ searchAllergiesList.add(AllergiesListVidaPlus.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ searchAllergiesList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "AllergyName": searchKey,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ });
+ }
+
+ Future addAllergies(AllergiesListVidaPlus allergy,
+ PatiantInformtion patientInfo, bool isNoKnown) async {
+ var hospitalGroudpId = await sharedPref.getString(DOCTOR_SETUP_ID);
+
+ if (!isNoKnown) {
+ allergy.allergyReactionDTOs!.forEach((value) {
+ value.patientID = patientInfo.patientMRN;
+ value.pomrid = int.parse(patientInfo.pomrId!);
+ value.allergyReactionMappingID = 1;
+ value.severity = value.severity ?? 1;
+ });
+ }
+ allergy.allergyReactionDTOs?.forEach((value) {
+ value.hospitalGroupID = hospitalGroudpId;
+ value.hospitalID = patientInfo.projectId;
+ });
+
+ var request = {
+ "patientsAllergyRevisionID": allergy.allergyRevisionID,
+ "patientMRN": patientInfo.patientMRN,
+ "allergyDiseaseType": 0,
+ "allergyTypeName": allergy.allergyTypeName,
+ "episodeId": patientInfo.episodeNo,
+ "isUpdatedByNurse": false,
+ "remarks": allergy.remark,
+ "createdBy": patientInfo.doctorId,
+ "createdOn": AppDateUtils.convertDateToFormat(
+ DateTime.now(), "yyyy-MM-dd kk:mm:ss"),
+ "assessmentId": 0,
+ "isActive": allergy.isActive,
+ "isActivePatientsAllergy": true,
+ "patientsAllergyReactionsDTOs": allergy.allergyReactionDTOs,
+ "dbCRUDOperation": 1,
+ "allergyID": allergy.allergyID,
+ "allergyName": allergy.allergyName,
+ "allergyTypeID": allergy.allergyTypeID,
+ };
+
+ if (isNoKnown) {
+ request['isAllergy'] = 'NO_KNOWN_ALLERGIES';
+ request['allergyName'] = "No Known Allergies";
+ request['userType'] = 'DOCTOR';
+ request['allergyTypeID'] = request['allergyID'] = 0;
+ request['isActive'] = true;
+ request['remarks'] = "";
+ request['isActivePatientsAllergy'] = true;
+ request['patientsAllergyReactionsDTOs'] = [];
+ }
+
+ hasError = false;
+
+ await baseAppClient.post(POST_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast("Allergies Saved Successfully");
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "listProgNotePatientAllergyDiseaseVM": [request],
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ });
+ }
+
+ Future resolveAllergies(
+ PatientAllergiesVidaPlus allergy, PatiantInformtion patientInfo) async {
+ /*changed request parameters based on the vida plus requested */
+
+ var doctorProfile = await sharedPref.getObj(LOGGED_IN_USER);
+ var hospitalGroudpId = await sharedPref.getString(DOCTOR_SETUP_ID);
+
+ List? reaction =
+ allergy.patientsAllergyReactionsDTOs!;
+ List? reactionRequest = [];
+ reaction.forEach((value) async {
+ reactionRequest.add(AllergyReactionDTOs(
+ patientID: patientInfo.patientMRN,
+ pomrid: int.parse(patientInfo.pomrId!),
+ hospitalGroupID: hospitalGroudpId,
+ allergyReactionMappingID: 0,
+ hospitalID: patientInfo.projectId,
+ isActive: value.isActive,
+ allergyReactionID: value.allergyReactionID,
+ allergyReactionName: value.allergyReactionName,
+ severity: value.severity));
+ });
+
+ var request = {
+ "pomrId": patientInfo.pomrId,
+ "patientMRN": patientInfo.patientMRN,
+ "allergyTypeName": allergy.allergyTypeName,
+ "assessmentId": 0,
+ "isActive": allergy.isActivePatientsAllergy,
+ "patientsAllergyReactionsDTOs": reactionRequest,
+ "dbCRUDOperation": 2,
+ "allergyID": allergy.allergyID,
+ "allergyName": allergy.allergyName,
+ "allergyTypeID": allergy.allergyTypeID,
+ "remarks": allergy.remark,
+ "projectId": patientInfo.projectId,
+ "editedBy": doctorProfile['List_MemberInformation'][0]['MemberID'],
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+ hasError = false;
+ await baseAppClient.post(RESOLVE_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast("Resolved Successfully");
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "listProgNotePatientAllergyDiseaseVM": [request]
+ });
+ }
+
+ Future updateAllergies(
+ PatientAllergiesVidaPlus allergy, PatiantInformtion patientInfo) async {
+ var doctorProfile = await sharedPref.getObj(LOGGED_IN_USER);
+ var hospitalGroudpId = await sharedPref.getString(DOCTOR_SETUP_ID);
+ List? reaction =
+ allergy.patientsAllergyReactionsDTOs!;
+ List? reactionRequest = [];
+ reaction.forEach((value) {
+ reactionRequest.add(AllergyReactionDTOs(
+ patientID: patientInfo.patientMRN,
+ pomrid: int.parse(patientInfo.pomrId!),
+ hospitalGroupID: hospitalGroudpId,
+ allergyReactionMappingID: 0,
+ hospitalID: patientInfo.projectId,
+ isActive: value.isActive,
+ allergyReactionID: value.allergyReactionID,
+ allergyReactionName: value.allergyReactionName,
+ severity: value.severity));
+ });
+
+ var request = {
+ "pomrId": patientInfo.pomrId,
+ "patientMRN": patientInfo.patientMRN,
+ "allergyTypeName": allergy.allergyTypeName,
+ "assessmentId": 0,
+ "isActive": allergy.isActivePatientsAllergy,
+ "isActivePatientsAllergy": allergy.isActivePatientsAllergy,
+ "patientsAllergyReactionsDTOs": reactionRequest,
+ "dbCRUDOperation": 2,
+ "allergyID": allergy.allergyID,
+ "allergyName": allergy.allergyName,
+ "allergyTypeID": allergy.allergyTypeID,
+ "remarks": allergy.remark,
+ "projectId": patientInfo.projectId,
+ "editedBy": doctorProfile['List_MemberInformation'][0]['MemberID'],
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+
+ hasError = false;
+
+ await baseAppClient.post(UPDATE_ALLERGIES,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast("Allergies Updated Successfully");
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: {
+ "listProgNotePatientAllergyDiseaseVM": [request]
+ });
+ }
+
+ saveHopi(Map req, PatiantInformtion patient) async {
+ var request = {
+ "clinicGroupId": patient.clinicGroupId, // patient.clinicGroupId
+ "clinicId": patient.clinicId,
+ "doctorId": patient.doctorId,
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID), //setup
+ "hospitalId": patient.projectId, //projectid
+ "patientId": patient.patientMRN,
+ "patientPomrId": patient.pomrId,
+ };
+ Map finalRequest = {}
+ ..addAll(request)
+ ..addAll(req);
+ hasError = false;
+ bool success = false;
+ await baseAppClient.post(CREATE_HOPI,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast("History Saved Successfully");
+ success = true;
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ DrAppToastMsg.showErrorToast(error);
+ super.error = error;
+ }, body: finalRequest);
+ return success;
+ }
+
+ getHopi(PatiantInformtion patient) async {
+ Map request = {
+ "patientId": patient.patientMRN,
+ "pomrId": patient.pomrId,
+ };
+ hasError = false;
+ hopiDetails.clear();
+ await baseAppClient.post(HOPI_DETAILS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['DetailHOPI']['resultData'].forEach((v) {
+ hopiDetails.add(GetHopiDetails.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getChiefComplaint(PatiantInformtion patient) async {
+ Map request = {
+ "ProjectID": patient.projectId,
+ "pomrId": patient.pomrId,
+ };
+ hasError = false;
+ patientChiefComplaintListVidaPlus.clear();
+ await baseAppClient.post(GET_CHIEF_COMPLAINT_VP,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListChiefComplaintDetails']['resultData'].forEach((v) {
+ patientChiefComplaintListVidaPlus
+ .add(GetChiefComplaintVidaPlus.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ DrAppToastMsg.showErrorToast(error);
+ }, body: request);
+ }
+
+ postChiefComplaintVidaPlus(
+ PatiantInformtion patient, String cheifComplaint) async {
+ Map request = {
+ "ListCreateChiefComplaint": [
+ {
+ "appointmentNo": patient.appointmentNo,
+ "pomrId": patient.pomrId,
+ "patientMRN": patient.patientMRN,
+ "chiefComplaint": cheifComplaint,
+ }
+ ],
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+ hasError = false;
+ await baseAppClient.post(POST_CHIEF_COMPLAINT_VP,
+ onSuccess: (dynamic response, int statusCode) {
+ print("Success");
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ searchChiefComplaintVidaPlus(PatiantInformtion patient, String CC) async {
+ Map request = {
+ "doctorId": patient.doctorId,
+ "searchParam": CC,
+ };
+ hasError = false;
+ searchChiefComplaintListVidaPlus.clear();
+ await baseAppClient.post(SEARCH_CHIEF_COMPLAINT_VP,
+ onSuccess: (dynamic response, int statusCode) {
+ searchChiefComplaintListVidaPlus.clear();
+ //
+ response['List_SearchChiefComplaint']['resultData'].forEach((v) {
+ searchChiefComplaintListVidaPlus.add(SearchChiefComplaint.fromJson(v));
+ });
+ }, onFailure: (String error, int statusCode) {
+ searchChiefComplaintListVidaPlus.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ searchDiagnosis(PatiantInformtion patient, String diagnosis) async {
+ Map request = {
+ "diseaseCode": diagnosis,
+ };
+ hasError = false;
+ clearSearchResult();
+
+ await baseAppClient.post(SEARCH_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['List_Diagnosis']['resultData']
+ .forEach((v) => searchDiagnosisList.add(SearchDiagnosis.fromJson(v)));
+ _processData();
+ }, onFailure: (String error, int statusCode) {
+ clearSearchResult();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ clearSearchResult() {
+ searchDiagnosisList.clear();
+ icdVersionList.clear();
+ }
+
+ void _processData() {
+ Set icdVersions = {};
+ for (var item in searchDiagnosisList) {
+ if (item.icdVersion != null) {
+ icdVersions.addAll(item.icdVersion ?? []);
+ }
+ }
+ icdVersionList = icdVersions.toList();
+ }
+
+ SearchDiagnosis? findParent(String selectedICD) {
+ for (var item in searchDiagnosisList) {
+ if (item.icdVersion != null &&
+ (item.icdVersion as List).contains(selectedICD)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ getDiagnosisType(PatiantInformtion patient) async {
+ Map request = {};
+ hasError = false;
+ diagnosisTypeList.clear();
+ await baseAppClient.post(DIAGNOSIS_TYPE,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListDiagnosisTypeModel']['resultData']
+ .forEach((v) {
+ diagnosisTypeList[v['name']] = v['diagnosisType'];
+ diagnosisTypeTypeMapWithIdAsKey[v['diagnosisType']] = v['name'];
+ });
+ }, onFailure: (String error, int statusCode) {
+ searchChiefComplaintListVidaPlus.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getConditionType(PatiantInformtion patient) async {
+ Map request = {};
+ hasError = false;
+ conditionTypeList.clear();
+ await baseAppClient.post(CONDITION_TYPE,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListDiagnosisCondition']['resultData']
+ .forEach((v) => conditionTypeList[v['itemName']] = v['id']);
+ ;
+ response['ListDiagnosisCondition']['resultData']
+ .forEach((v) => conditionTypeMapWithIdAsKey[v['id']] = v['itemName']);
+ ;
+ }, onFailure: (String error, int statusCode) {
+ searchChiefComplaintListVidaPlus.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ auditDiagnosis(
+ PatiantInformtion patient,
+ String patientProblemRevisionID,
+ ) async {
+ print('the setup id is ${await sharedPref.getString(DOCTOR_SETUP_ID)}');
+ Map request = {
+ "patientProblemRevisionId": patientProblemRevisionID,
+ "ProjectID": patient.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+ hasError = false;
+ auditDiagnosislist.clear();
+ await baseAppClient.post(AUDIT_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListDaignosisAudit']['resultData']
+ .forEach((v) => auditDiagnosislist.add(AuditDiagnosis.fromJson(v)));
+ showAuditBottomSheet = auditDiagnosislist.isNotEmpty;
+ }, onFailure: (String error, int statusCode) {
+ auditDiagnosislist.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getPreviousDiagnosis(PatiantInformtion patient) async {
+ Map request = {
+ "HospitalGroupID": await sharedPref.getString(DOCTOR_SETUP_ID), //setup
+ "hospitalId": patient.projectId,
+ "patientId": patient.patientId,
+ "patientPomrId": patient.pomrId,
+ "startRow": 0,
+ "endRow": 1000,
+ "ProjectID": patient.projectId
+ //todo just for the test as the create diagnosis is still not working
+ // "HospitalGroupID": 105,
+ // "hospitalId": 313,
+ // "patientId": 70010976,
+ // "patientPomrId": 8414,
+ // "startRow": 0,
+ // "endRow": 2,
+ // "ProjectID": 313
+ };
+ hasError = false;
+ patientPreviousDiagnosisList.clear();
+ await baseAppClient.post(PREVIOUS_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListDiagnosisPrviousDetials']['resultData'].forEach((v) =>
+ patientPreviousDiagnosisList
+ .add(PatientPreviousDiagnosis.fromJson(v)));
+ }, onFailure: (String error, int statusCode) {
+ patientPreviousDiagnosisList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getDiagnosis(PatiantInformtion patient) async {
+ Map request = {
+ // "hospitalGroupId": 105,
+ // "hospitalId": 313,
+ // "patientId": 70023498,
+ // "patientPomrId": 9907,
+ // "startRow": 0,
+ // "endRow": 10,
+ // "isSelected": true,
+ // "ProjectID": 313
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "hospitalId": patient.projectId,
+ "patientId": patient.patientId,
+ "patientPomrId": patient.pomrId,
+ "startRow": 0,
+ "endRow": 1000000,
+ "ProjectID": patient.projectId
+ };
+ hasError = false;
+ await baseAppClient.post(GET_LIST_OF_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ patientDiagnosisList.clear();
+ response['ListDiagnosisDetailsSearch']['resultData'].forEach((v) =>
+ patientDiagnosisList.add(PatientPreviousDiagnosis.fromJson(v)));
+ }, onFailure: (String error, int statusCode) {
+ patientDiagnosisList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ removeDiagnosis(PatiantInformtion patientInfo, String? patientProblemId,
+ String? problemId, String? deletedRemarks) async {
+ Map request = {
+ "patientProblemId": patientProblemId,
+ "patientId": patientInfo.patientId,
+ "problemId": problemId,
+ "deletedRemarks": deletedRemarks,
+ "ProjectID": patientInfo.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ //todo just for the test as the create diagnosis is still not working
+ // "patientProblemId": 13691,
+ // "patientId": 70010986,
+ // "problemId": 41698,
+ // "deletedRemarks": "kethees test",
+ // "ProjectID": 313,
+ // "setupId": 105
+ };
+ hasError = false;
+ var success = false;
+ patientPreviousDiagnosisList.clear();
+ await baseAppClient.post(REMOVE_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast(response['ListDiagnosisRemove']['message']);
+ success = true;
+ }, onFailure: (String error, int statusCode) {
+ patientPreviousDiagnosisList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ return success;
+ }
+
+ favoriteDiagnosis(
+ PatiantInformtion patientInfo,
+ ) async {
+ Map? user = await sharedPref.getObj(LOGGED_IN_USER);
+
+ Map request = {
+ "projectId": patientInfo.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "userId": user?['List_MemberInformation'][0]['MemberID'],
+ "favoritesType": "DIAGNOSIS",
+ "clinicId": patientInfo.clinicId,
+ "ProjectID": patientInfo.projectId,
+ };
+ hasError = false;
+ favoriteDiagnosisDetailsList.clear();
+ await baseAppClient.post(FAVORITE_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListDiagnosisGetFavourite']['resultData'].forEach((v) =>
+ favoriteDiagnosisDetailsList.add(FavoriteDiseaseDetails.fromJson(v)));
+ }, onFailure: (String error, int statusCode) {
+ favoriteDiagnosisDetailsList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getPhysicalExamination(
+ PatiantInformtion patientInfo,
+ ) async {
+ Map? user = await sharedPref.getObj(LOGGED_IN_USER);
+
+ Map request =
+ // {
+ // "patientId": 70024978,
+ // "pomrId": 10819,
+ // "hospitalId": 313,
+ // "hospitalGroupId": 105,
+ // "ProjectID": 313
+ // };
+
+ {
+ "patientId": patientInfo.patientId,
+ "pomrId": patientInfo.pomrId,
+ "hospitalId": patientInfo.projectId,
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "ProjectID": patientInfo.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID)
+ };
+ hasError = false;
+ patientPhysicalExaminationList.clear();
+ await baseAppClient.post(SEARCH_PHYSICAL_EXAMINATION,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListPhysicalExam']['resultData'].forEach((v) =>
+ patientPhysicalExaminationList
+ .add(PatientPhysicalExamination.fromJson(v)));
+ }, onFailure: (String error, int statusCode) {
+ physicalExaminationList.clear();
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ Future postPhysicalExamination(
+ PatiantInformtion patientInfo, List physicalExamination) async {
+ List jsonListOfPhysicalExamination = [];
+ physicalExamination.forEach((value) => jsonListOfPhysicalExamination
+ .add(value.createPhysicalExaminationFromCategory()));
+
+ Map request = {
+ "ProjectID": patientInfo.projectId,
+ "setupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "listCreatPhysicalExam": jsonListOfPhysicalExamination
+ };
+ hasError = false;
+ var success = false;
+ await baseAppClient.post(POST_PHYSICAL_EXAM,
+ onSuccess: (dynamic response, int statusCode) {
+ DrAppToastMsg.showSuccesToast(response['ListPhysicalExam']['message']);
+ success = true;
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ success = false;
+ }, body: request);
+
+ return success;
+ }
+
+ getGeneralSpeciality(PatiantInformtion patientInfo) async {
+ Map request = {
+ "ProjectID": patientInfo.projectId,
+ };
+ hasError = false;
+ generalSpeciality.clear();
+ await baseAppClient.post(GET_GENERAL_SPECIALITY,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListGeneralSpeciality']['resultData'].forEach((v) =>
+ v['categories'].forEach(
+ (cat) => generalSpeciality.add(GeneralSpeciality.fromJson(cat))));
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ generalSpeciality.clear();
+ super.error = error;
+ }, body: request);
+ }
+
+ Future addToFavoriteDiagnosis(PatiantInformtion paitientInfo,
+ String doctorName, String subFavoriteCode, dynamic? userId) async {
+ Map request = {
+ "ProjectID": paitientInfo.projectId,
+ "listDiagnosisFavourite": [
+ {
+ "createdBy": doctorName,
+ "favoritesType": "DIAGNOSIS",
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "hospitalId": paitientInfo.projectId,
+ "subFavoritesCode": subFavoriteCode,
+ "userId": userId
+ }
+ ]
+ };
+ hasError = false;
+ var isFavoriteAdded = false;
+ await baseAppClient.post(ADD_TO_FAVORITE_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) {
+ var result = response['ListDiagnosisAddFavourite']['resultData'];
+ isFavoriteAdded = true;
+ if ((result is List) && (result as List).isEmpty) {
+ if (response['ListDiagnosisAddFavourite']['message'] != null)
+ DrAppToastMsg.showErrorToast(
+ response['ListDiagnosisAddFavourite']['message']);
+ else
+ DrAppToastMsg.showErrorToast("Unable to Add");
+ } else {
+ if (response['ListDiagnosisAddFavourite']['message'] != null)
+ DrAppToastMsg.showSuccesToast(
+ response['ListDiagnosisAddFavourite']['message']);
+ else
+ DrAppToastMsg.showErrorToast("Diagnosis Added To Favorite");
+ }
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ isFavoriteAdded = false;
+ super.error = error;
+ }, body: request);
+
+ return isFavoriteAdded;
+ }
+
+ Future convertPreviousDiagnosisCurrent(
+ PatiantInformtion patient, PatientPreviousDiagnosis diagnosis) async {
+ Map? user = await sharedPref.getObj(LOGGED_IN_USER);
+ Map request = {
+ "patientProblemRevisionId": diagnosis.patientProblemRevisionId,
+ "patientId": patient.patientId,
+ "doctorId": patient.doctorId,
+ "pomrId": patient.pomrId,
+ "appointmentId": patient.appointmentNo,
+ "createdBy": patient.doctorId,
+ "hospitalId": patient.projectId,
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "clinicGroupId": diagnosis.clinicGroupId ?? patient.clinicGroupId,
+ "clinicId": diagnosis.clinicId,
+ "isSelected": true,
+ "ProjectID": patient.projectId
+ };
+ hasError = false;
+ var success = false;
+ await baseAppClient.post(MAKE_PREVIOUS_AS_CURRENT_DIAGNOSIS,
+ onSuccess: (dynamic response, int statusCode) async {
+ DrAppToastMsg.showSuccesToast(
+ response['ContinuePreviousEpisode']['message']);
+ success = true;
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ return success;
+ }
+
+ Future getProgressNoteNew(PatiantInformtion patientInformation) async {
+ Map request = {
+ "hospitalGroupId": await sharedPref.getString(DOCTOR_SETUP_ID),
+ "hospitalId": patientInformation.projectId,
+ "patientId": patientInformation.patientId,
+ "patientPomrId": patientInformation.pomrId,
+ "endRow": 10000, // because no information is provided for the end row
+ "startRow": 0,
+ "ProjectID": patientInformation.projectId
+ };
+ hasError = false;
+ patientProgressNoteListVidaPlus.clear();
+ await baseAppClient.post(GET_PROGRESS_NOTE,
+ onSuccess: (dynamic response, int statusCode) {
+ print("Success");
+ response['ListProgressNote']['resultData'].forEach((v) {
+ v['data'].forEach((progressNote) {
+ patientProgressNoteListVidaPlus
+ .add(ProgressNote.fromJson(progressNote));
});
+ });
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ }
+
+ getSpecialityDetails(String speciality, int? specialityId,
+ PatiantInformtion patientInfo) async {
+ Map? user = await sharedPref.getObj(LOGGED_IN_USER);
+ var userId = user?['List_MemberInformation'][0]['MemberID'];
+ Map request = {"searchParam": speciality};
+ hasError = false;
+ specialityDetails.clear();
+ List categoryData = [];
+ await baseAppClient.post(GET_SPECIALITY_DETAILS,
+ onSuccess: (dynamic response, int statusCode) {
+ response['ListEyeGeneralSpeciality']['resultData'].forEach((value) =>
+ categoryData.add(Category.fromJson(
+ value,
+ specialityId,
+ speciality,
+ patientInfo.pomrId,
+ patientInfo.patientId,
+ user?['List_MemberInformation'][0]['MemberID'])));
+ }, onFailure: (String error, int statusCode) {
+ hasError = true;
+ super.error = error;
+ }, body: request);
+ if (!hasError) {
+ specialityDetails[speciality] = categoryData;
+ }
+ }
+
+ Future