TP-52572 | merge conflict resolve
This commit is contained in:
Submodule RN-UI-LIB updated: 9d8a8dcdc3...fe38294725
@@ -1,4 +1,5 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.google.gms.google-services"
|
||||
apply plugin: "com.google.firebase.crashlytics"
|
||||
apply plugin: 'com.google.firebase.firebase-perf'
|
||||
|
||||
@@ -133,8 +134,8 @@ def reactNativeArchitectures() {
|
||||
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
||||
}
|
||||
|
||||
def VERSION_CODE = 120
|
||||
def VERSION_NAME = "2.7.2"
|
||||
def VERSION_CODE = 123
|
||||
def VERSION_NAME = "2.7.5"
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
@@ -315,7 +316,10 @@ dependencies {
|
||||
|
||||
implementation "com.github.anrwatchdog:anrwatchdog:1.4.0"
|
||||
|
||||
//implementation 'com.navi.medici:alfred:v1.0.2'
|
||||
implementation 'com.navi.android:alfred:1.1.1'
|
||||
implementation(platform("com.google.firebase:firebase-bom:32.2.3"))
|
||||
implementation("com.google.firebase:firebase-config-ktx")
|
||||
implementation("com.google.firebase:firebase-analytics-ktx")
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.avapp;
|
||||
|
||||
import static android.app.Activity.RESULT_CANCELED;
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
import static com.avapp.MainApplication.isAlfredEnabledFromFirebase;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.location.LocationManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -20,26 +20,18 @@ import com.facebook.react.bridge.Promise;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||
import com.facebook.react.uimanager.UIBlock;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.navi.alfred.AlfredManager;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Base64;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -47,7 +39,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -154,50 +145,52 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
|
||||
@ReactMethod
|
||||
public void setUserId(String userId) {
|
||||
//AlfredManager.config.setUserId(userId);
|
||||
if (isAlfredEnabledFromFirebase) {
|
||||
AlfredManager.INSTANCE.getConfig$navi_alfred_release().setUserId(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void handleSWWEvent(String message, String stack, String name) { //<String, Object>
|
||||
HashMap<String, String> properties = new HashMap<>();
|
||||
properties.put("message", message);
|
||||
properties.put("stack", stack);
|
||||
properties.put("name", name);
|
||||
//AlfredManager.INSTANCE.handleSWWEvent("Cosmos", properties);
|
||||
if (isAlfredEnabledFromFirebase) {
|
||||
HashMap<String, String> properties = new HashMap<>();
|
||||
properties.put("message", message);
|
||||
properties.put("stack", stack);
|
||||
properties.put("name", name);
|
||||
AlfredManager.INSTANCE.handleSWWEvent(properties);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setCodePushVersion(String codePushVersion) {
|
||||
if (codePushVersion != null) {
|
||||
//AlfredManager.config.setCodePushVersion(codePushVersion);
|
||||
if (isAlfredEnabledFromFirebase && codePushVersion != null) {
|
||||
AlfredManager.INSTANCE.getConfig$navi_alfred_release().setCodePushVersion(codePushVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setPhoneNumber(String phoneNumber) {
|
||||
if (phoneNumber != null) {
|
||||
//AlfredManager.config.setPhoneNumber(phoneNumber);
|
||||
if (isAlfredEnabledFromFirebase && phoneNumber != null) {
|
||||
AlfredManager.INSTANCE.getConfig$navi_alfred_release().setPhoneNumber(phoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setEmailId(String emailId) {
|
||||
if (emailId != null) {
|
||||
//AlfredManager.config.setAgentEmailId(emailId);
|
||||
if (isAlfredEnabledFromFirebase && emailId != null) {
|
||||
AlfredManager.INSTANCE.getConfig$navi_alfred_release().setAgentEmailId(emailId);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setBottomSheetView(Integer refID) {
|
||||
if (refID != null) {
|
||||
if (isAlfredEnabledFromFirebase && refID != null) {
|
||||
UIManagerModule uiManagerModule = RNContext.getNativeModule(UIManagerModule.class);
|
||||
if (uiManagerModule != null) {
|
||||
try {
|
||||
uiManagerModule.addUIBlock(nativeViewHierarchyManager -> {
|
||||
Log.d("Alfred", "setBottomSheetView nativeViewHierarchyManager:" + nativeViewHierarchyManager);
|
||||
View view = nativeViewHierarchyManager.resolveView(refID);
|
||||
Log.d("Alfred", "setBottomSheetView view:" + view);
|
||||
//AlfredManager.INSTANCE.setBottomSheetView(view);
|
||||
AlfredManager.INSTANCE.setBottomSheetView(view);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
Log.d("Alfred", "setBottomSheetView error:" + error);
|
||||
@@ -208,7 +201,9 @@ public class DeviceUtilsModule extends ReactContextBaseJavaModule {
|
||||
|
||||
@ReactMethod
|
||||
public void clearBottomSheet() {
|
||||
//AlfredManager.INSTANCE.clearBottomSheetView();
|
||||
if (isAlfredEnabledFromFirebase) {
|
||||
AlfredManager.INSTANCE.clearBottomSheetView();
|
||||
}
|
||||
}
|
||||
|
||||
private static File convertBase64ToFile(Context context, String base64Data, String format, String fileName) {
|
||||
|
||||
@@ -1,50 +1,137 @@
|
||||
package com.avapp;
|
||||
|
||||
import static com.avapp.MainApplication.isAlfredEnabledFromFirebase;
|
||||
|
||||
import com.avapp.utils.AlfredFirebaseHelper;
|
||||
import com.avapp.utils.FirebaseRemoteConfigHelper;
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.navi.alfred.AlfredManager;
|
||||
import com.navi.alfred.utils.CommonUtilsKt;
|
||||
|
||||
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "AVAPP";
|
||||
}
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(null);
|
||||
}
|
||||
/**
|
||||
* Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
|
||||
* you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
|
||||
* (Paper).
|
||||
*/
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new MainActivityDelegate(this, getMainComponentName());
|
||||
}
|
||||
public static class MainActivityDelegate extends ReactActivityDelegate {
|
||||
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
|
||||
super(activity, mainComponentName);
|
||||
}
|
||||
public class MainActivity extends ReactActivity implements AlfredFirebaseHelper {
|
||||
|
||||
private static int appInForegroundCounter = 0;
|
||||
private boolean cruiseApiCalled = false;
|
||||
public static boolean hasAlfredRecordingStarted = false;
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected ReactRootView createRootView() {
|
||||
ReactRootView reactRootView = new ReactRootView(getContext());
|
||||
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
|
||||
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
|
||||
return reactRootView;
|
||||
protected String getMainComponentName() {
|
||||
return "AVAPP";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConcurrentRootEnabled() {
|
||||
// If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
|
||||
// More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(null);
|
||||
FirebaseRemoteConfigHelper.setAlfredFirebaseHelper(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instance of the {@link ReactActivityDelegate}. There the RootView is created and
|
||||
* you can specify the renderer you wish to use - the new renderer (Fabric) or the old renderer
|
||||
* (Paper).
|
||||
*/
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new MainActivityDelegate(this, getMainComponentName());
|
||||
}
|
||||
|
||||
public static class MainActivityDelegate extends ReactActivityDelegate {
|
||||
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
|
||||
super(activity, mainComponentName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ReactRootView createRootView() {
|
||||
ReactRootView reactRootView = new ReactRootView(getContext());
|
||||
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
|
||||
reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
|
||||
return reactRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConcurrentRootEnabled() {
|
||||
// If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
|
||||
// More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
if (isAlfredEnabledFromFirebase && AlfredManager.INSTANCE.isAlfredRecordingEnabled() && cruiseApiCalled) {
|
||||
AlfredManager.INSTANCE.handleTouchEvent(ev, BuildConfig.APP_NAME, BuildConfig.APP_NAME);
|
||||
}
|
||||
return super.dispatchTouchEvent(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
appInForegroundCounter++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (isAlfredEnabledFromFirebase && !hasAlfredRecordingStarted) {
|
||||
callCruiseAndStartAlfredRecording();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
appInForegroundCounter--;
|
||||
if (isAlfredEnabledFromFirebase && AlfredManager.INSTANCE.isAlfredRecordingEnabled() && cruiseApiCalled) {
|
||||
if (!isAppInForeground()) {
|
||||
AlfredManager.INSTANCE.stopRecording();
|
||||
hasAlfredRecordingStarted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean isAppInForeground() {
|
||||
return appInForegroundCounter >= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callCruiseAndStartAlfredRecording() {
|
||||
if (cruiseApiCalled) {
|
||||
startAlfredRecording();
|
||||
} else {
|
||||
AlfredManager.INSTANCE.getAlfredCruiseInfo(response -> {
|
||||
cruiseApiCalled = true;
|
||||
startAlfredRecording();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void startAlfredRecording() {
|
||||
if (AlfredManager.INSTANCE.isAlfredRecordingEnabled() && !hasAlfredRecordingStarted) {
|
||||
try {
|
||||
AlfredManager.INSTANCE.startRecording(
|
||||
this,
|
||||
this.getWindow().getDecorView().getRootView(),
|
||||
BuildConfig.APP_NAME,
|
||||
BuildConfig.APP_NAME,
|
||||
this
|
||||
);
|
||||
hasAlfredRecordingStarted = true;
|
||||
} catch (Exception e) {
|
||||
CommonUtilsKt.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package com.avapp;
|
||||
|
||||
|
||||
import static com.avapp.utils.Constants.APP_IN_FOREGROUND;
|
||||
import static com.avapp.utils.Constants.LINE_NUMBER;
|
||||
import static com.avapp.utils.Constants.METHOD_NAME;
|
||||
import static com.avapp.utils.Constants.STACK_TRACE;
|
||||
import static com.google.firebase.analytics.FirebaseAnalytics.Param.SCREEN_NAME;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.avapp.utils.FirebaseRemoteConfigHelper;
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
@@ -12,100 +18,169 @@ import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import com.avapp.newarchitecture.MainApplicationReactNativeHost;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.anrwatchdog.ANRWatchDog;
|
||||
import com.microsoft.codepush.react.CodePush;
|
||||
import com.navi.alfred.AlfredConfig;
|
||||
import com.navi.alfred.AlfredManager;
|
||||
|
||||
import android.database.CursorWindow;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
|
||||
public static boolean isAlfredEnabledFromFirebase = false;
|
||||
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new ReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
packages.add(new DeviceUtilsModulePackage());
|
||||
packages.add(new ScreenshotBlockerModulePackage());
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSBundleFile() {
|
||||
return CodePush.getJSBundleFile();
|
||||
}
|
||||
};
|
||||
|
||||
private final ReactNativeHost mNewArchitectureNativeHost =
|
||||
new MainApplicationReactNativeHost(this);
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
return mNewArchitectureNativeHost;
|
||||
} else {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
packages.add(new DeviceUtilsModulePackage());
|
||||
packages.add(new ScreenshotBlockerModulePackage());
|
||||
return packages;
|
||||
}
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
@Override
|
||||
protected String getJSBundleFile() {
|
||||
return CodePush.getJSBundleFile();
|
||||
}
|
||||
};
|
||||
private final ReactNativeHost mNewArchitectureNativeHost =
|
||||
new MainApplicationReactNativeHost(this);
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
return mNewArchitectureNativeHost;
|
||||
} else {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// If you opted-in for the New Architecture, we enable the TurboModule system
|
||||
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// If you opted-in for the New Architecture, we enable the TurboModule system
|
||||
ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
FirebaseRemoteConfigHelper.init();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
|
||||
AlfredConfig alfredConfig = new AlfredConfig(BuildConfig.APP_NAME, String.valueOf(BuildConfig.VERSION_CODE), BuildConfig.VERSION_NAME, BuildConfig.BUILD_FLAVOR, BuildConfig.API_KEY);
|
||||
AlfredManager.INSTANCE.init(alfredConfig, this);
|
||||
setupAlfredANRWatchDog(alfredConfig);
|
||||
setupAlfredCrashReporting(alfredConfig);
|
||||
|
||||
// https://github.com/rt2zz/redux-persist/issues/284#issuecomment-1011214066
|
||||
try {
|
||||
Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
|
||||
field.setAccessible(true);
|
||||
field.set(null, 20 * 1024 * 1024); //20MB
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/rt2zz/redux-persist/issues/284#issuecomment-1011214066
|
||||
try {
|
||||
Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
|
||||
field.setAccessible(true);
|
||||
field.set(null, 20 * 1024 * 1024); //20MB
|
||||
} catch (Exception e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
|
||||
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
*
|
||||
* @param context
|
||||
* @param reactInstanceManager
|
||||
*/
|
||||
private static void initializeFlipper(
|
||||
Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
try {
|
||||
/**
|
||||
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
|
||||
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
*
|
||||
* @param context
|
||||
* @param reactInstanceManager
|
||||
*/
|
||||
private static void initializeFlipper(
|
||||
Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
try {
|
||||
/*
|
||||
We use reflection here to pick up the class that initializes Flipper,
|
||||
since Flipper library is not available in release mode
|
||||
*/
|
||||
Class<?> aClass = Class.forName("com.avapp.ReactNativeFlipper");
|
||||
aClass
|
||||
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
|
||||
.invoke(null, context, reactInstanceManager);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Class<?> aClass = Class.forName("com.avapp.ReactNativeFlipper");
|
||||
aClass
|
||||
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
|
||||
.invoke(null, context, reactInstanceManager);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAlfredANRWatchDog(AlfredConfig alfredConfig) {
|
||||
new ANRWatchDog().setIgnoreDebugger(true).setReportMainThreadOnly().setANRListener(error -> {
|
||||
if (error.getCause().getStackTrace().length == 0) {
|
||||
return;
|
||||
}
|
||||
Map<String, String> anrEventProperties = new HashMap<>();
|
||||
anrEventProperties.put(SCREEN_NAME, BuildConfig.APP_NAME);
|
||||
anrEventProperties.put(METHOD_NAME, error.getCause().getStackTrace()[0].getMethodName());
|
||||
anrEventProperties.put(LINE_NUMBER, String.valueOf(error.getCause().getStackTrace()[0].getLineNumber()));
|
||||
anrEventProperties.put(APP_IN_FOREGROUND, MainActivity.isAppInForeground().toString());
|
||||
|
||||
if (isAlfredEnabledFromFirebase && AlfredManager.INSTANCE.isAlfredRecordingEnabled() && alfredConfig.getAnrEnableStatus()) {
|
||||
anrEventProperties.put(STACK_TRACE, error.getCause().getStackTrace()[0].toString());
|
||||
AlfredManager.INSTANCE.handleAnrEvent(anrEventProperties);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void setupAlfredCrashReporting(AlfredConfig alfredConfig) {
|
||||
Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> {
|
||||
if ((exception.getStackTrace() == null) || (exception.getStackTrace().length == 0)) {
|
||||
if (defaultHandler != null) {
|
||||
defaultHandler.uncaughtException(thread, exception);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Map<String, String> crashEventProperties = new HashMap<>();
|
||||
crashEventProperties.put(SCREEN_NAME, BuildConfig.APP_NAME);
|
||||
crashEventProperties.put(METHOD_NAME, exception.getStackTrace()[0].getMethodName());
|
||||
crashEventProperties.put(LINE_NUMBER, String.valueOf(exception.getStackTrace()[0].getLineNumber()));
|
||||
crashEventProperties.put(APP_IN_FOREGROUND, MainActivity.isAppInForeground().toString());
|
||||
|
||||
if (isAlfredEnabledFromFirebase && AlfredManager.INSTANCE.isAlfredRecordingEnabled() && alfredConfig.getCrashEnableStatus()) {
|
||||
StackTraceElement stackTraceElement = exception.getStackTrace()[0];
|
||||
if (stackTraceElement != null) {
|
||||
crashEventProperties.put(STACK_TRACE, stackTraceElement.toString());
|
||||
}
|
||||
AlfredManager.INSTANCE.handleCrashEvent(crashEventProperties);
|
||||
}
|
||||
} finally {
|
||||
if (defaultHandler != null) {
|
||||
defaultHandler.uncaughtException(thread, exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.avapp.utils;
|
||||
|
||||
public interface AlfredFirebaseHelper {
|
||||
void callCruiseAndStartAlfredRecording();
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.avapp.utils;
|
||||
|
||||
import static com.avapp.MainActivity.hasAlfredRecordingStarted;
|
||||
import static com.avapp.MainApplication.isAlfredEnabledFromFirebase;
|
||||
|
||||
import com.avapp.BuildConfig;
|
||||
import com.avapp.R;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigValue;
|
||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings;
|
||||
|
||||
public class FirebaseRemoteConfigHelper {
|
||||
|
||||
private static FirebaseRemoteConfig remoteConfig;
|
||||
private static final long CONFIG_SYNC_INTERVAL = 60 * 60;
|
||||
|
||||
public static final String DISABLE_ALFRED_LOGS = "DISABLE_ALFRED_LOGS";
|
||||
public static final String ALFRED_ENABLED = "ALFRED_ENABLED";
|
||||
|
||||
private static AlfredFirebaseHelper alfredFirebaseHelper;
|
||||
|
||||
public static void setAlfredFirebaseHelper(AlfredFirebaseHelper alfredFirebaseHelper) {
|
||||
FirebaseRemoteConfigHelper.alfredFirebaseHelper = alfredFirebaseHelper;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
remoteConfig = getFirebaseRemoteConfig();
|
||||
}
|
||||
|
||||
private static FirebaseRemoteConfig getFirebaseRemoteConfig() {
|
||||
FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
|
||||
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setMinimumFetchIntervalInSeconds(BuildConfig.DEBUG ? 0 : CONFIG_SYNC_INTERVAL).build();
|
||||
remoteConfig.setConfigSettingsAsync(configSettings);
|
||||
remoteConfig.setDefaultsAsync(R.xml.default_xml_config);
|
||||
remoteConfig.fetchAndActivate().addOnCompleteListener(task -> {
|
||||
isAlfredEnabledFromFirebase = FirebaseRemoteConfigHelper.getBoolean(ALFRED_ENABLED);
|
||||
if (alfredFirebaseHelper != null && isAlfredEnabledFromFirebase && !hasAlfredRecordingStarted) {
|
||||
alfredFirebaseHelper.callCruiseAndStartAlfredRecording();
|
||||
}
|
||||
});
|
||||
return remoteConfig;
|
||||
}
|
||||
|
||||
private static FirebaseRemoteConfigValue getRawValue(String key) {
|
||||
try {
|
||||
FirebaseRemoteConfigValue rawValue = remoteConfig.getValue(key);
|
||||
return rawValue.getSource() == FirebaseRemoteConfig.VALUE_SOURCE_STATIC ? null : rawValue;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean getRawBoolean(String key) {
|
||||
FirebaseRemoteConfigValue rawValue = getRawValue(key);
|
||||
return rawValue != null ? rawValue.asBoolean() : null;
|
||||
}
|
||||
|
||||
public static String getString(String key) {
|
||||
try {
|
||||
return remoteConfig.getString(key);
|
||||
} catch (Exception e) {
|
||||
return FirebaseRemoteConfig.DEFAULT_VALUE_FOR_STRING;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key) {
|
||||
try {
|
||||
return remoteConfig.getBoolean(key);
|
||||
} catch (Exception e) {
|
||||
return FirebaseRemoteConfig.DEFAULT_VALUE_FOR_BOOLEAN;
|
||||
}
|
||||
}
|
||||
|
||||
public static double getDouble(String key) {
|
||||
try {
|
||||
return remoteConfig.getDouble(key);
|
||||
} catch (Exception e) {
|
||||
return FirebaseRemoteConfig.DEFAULT_VALUE_FOR_DOUBLE;
|
||||
}
|
||||
}
|
||||
|
||||
public static long getLong(String key) {
|
||||
try {
|
||||
return remoteConfig.getLong(key);
|
||||
} catch (Exception e) {
|
||||
return FirebaseRemoteConfig.DEFAULT_VALUE_FOR_LONG;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
android/app/src/main/res/xml/default_xml_config.xml
Normal file
15
android/app/src/main/res/xml/default_xml_config.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~
|
||||
~ * Copyright © 2019-2023 by Navi Technologies Limited
|
||||
~ * All rights reserved. Strictly confidential
|
||||
~
|
||||
-->
|
||||
|
||||
<defaultsMap>
|
||||
<entry>
|
||||
<key>ALFRED_ENABLED</key>
|
||||
<value>false</value>
|
||||
</entry>
|
||||
</defaultsMap>
|
||||
@@ -39,7 +39,7 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
hermesEnabled=true
|
||||
|
||||
MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
|
||||
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
|
||||
MYAPP_UPLOAD_STORE_PASSWORD=Navi@123
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "AV_APP",
|
||||
"version": "2.7.2",
|
||||
"buildNumber": "120",
|
||||
"version": "2.7.5",
|
||||
"buildNumber": "123",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android:dev": "yarn move:dev && react-native run-android",
|
||||
@@ -9,13 +9,13 @@
|
||||
"android:prod": "yarn move:prod && react-native run-android",
|
||||
"android-field:dev": "yarn move:dev && react-native run-android --variant=fieldAgentsQADebug",
|
||||
"android-field:qa": "yarn move:qa && react-native run-android --variant=fieldAgentsQADebug",
|
||||
"android-field:prod": "yarn move:prod && react-native run-android --variant=fieldAgentsQADebug",
|
||||
"android-field:prod": "yarn move:prod && react-native run-android --variant=fieldAgentsProdDebug",
|
||||
"release-field:dev": "yarn move:dev && react-native run-android --variant=fieldAgentsQARelease && cd android && ./gradlew assemblefieldAgentsQARelease",
|
||||
"release-field:qa": "yarn move:qa && react-native run-android --variant=fieldAgentsQARelease && cd android && ./gradlew assemblefieldAgentsQARelease",
|
||||
"release-field:prod": "yarn move:prod && react-native run-android --variant=fieldAgentsProdRelease && cd android && ./gradlew assemblefieldAgentsProdRelease",
|
||||
"android-calling:dev": "yarn move:dev && react-native run-android --variant=callingAgentsQADebug",
|
||||
"android-calling:qa": "yarn move:qa && react-native run-android --variant=callingAgentsQADebug",
|
||||
"android-calling:prod": "yarn move:prod && react-native run-android --variant=callingAgentsQADebug",
|
||||
"android-calling:prod": "yarn move:prod && react-native run-android --variant=callingAgentsProdDebug",
|
||||
"release-calling:dev": "yarn move:dev && react-native run-android --variant=callingAgentsQARelease && cd android && ./gradlew assemblecallingAgentsQARelease",
|
||||
"release-calling:qa": "yarn move:qa && react-native run-android --variant=callingAgentsQARelease && cd android && ./gradlew assemblecallingAgentsQARelease",
|
||||
"release-calling:prod": "yarn move:dev && react-native run-android --variant=callingAgentsProdRelease && cd android && ./gradlew assemblecallingAgentsProdRelease",
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
setAuthData,
|
||||
setSelectedAgent,
|
||||
setIsExternalAgent,
|
||||
setIsAgentPerformanceDashboardVisible,
|
||||
} from '../reducer/userSlice';
|
||||
import axiosInstance, { ApiKeys, API_STATUS_CODE, getApiUrl } from '../components/utlis/apiHelper';
|
||||
import {
|
||||
@@ -279,8 +280,10 @@ export const getAgentDetail = (callbackFn?: () => void) => (dispatch: AppDispatc
|
||||
if (response.status === API_STATUS_CODE.OK) {
|
||||
const roles: string[] = response?.data?.roles || [];
|
||||
const isExternalAgent: boolean = response?.data?.isExternalAgent;
|
||||
const isAgentPerformanceDashboardVisible: boolean = response?.data?.featureFlags?.fieldAgentPerformanceDashboardEnabled || false;
|
||||
dispatch(setAgentRole(roles));
|
||||
dispatch(setIsExternalAgent(isExternalAgent));
|
||||
dispatch(setIsAgentPerformanceDashboardVisible(isAgentPerformanceDashboardVisible));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
|
||||
@@ -81,6 +81,10 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
description: 'Cases unpinned',
|
||||
},
|
||||
FA_VISIT_PLAN_UPDATED: { name: 'FA_VISIT_PLAN_UPDATED', description: 'Updated cases pinned' },
|
||||
FA_VISIT_PLAN_BUTTON_CLICKED : {
|
||||
name: 'FA_VISIT_PLAN_BUTTON_CLICKED',
|
||||
description : 'Click on visit plan button on bottom navigation bar',
|
||||
},
|
||||
|
||||
// Login screen
|
||||
AV_LOGIN_SCREEN_LOAD: { name: 'FA_LOGIN_SCREEN_LOAD', description: 'Login page loaded' },
|
||||
@@ -155,6 +159,10 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
name: 'FA_CASE_LIST_FILTER_BUTTON_CLICKED',
|
||||
description: 'Case list filter CTA clicked',
|
||||
},
|
||||
FA_CASE_LIST_BUTTON_CLICKED :{
|
||||
name : 'FA_CASE_LIST_BUTTON_CLICKED',
|
||||
description :'Clicks on case list button on bottom navigation bar',
|
||||
},
|
||||
|
||||
// TODO LIST
|
||||
AV_TODO_LIST_LOAD: {
|
||||
@@ -241,6 +249,10 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
|
||||
//PROFILE PAGE
|
||||
AV_PROFILE_PAGE_LOADED: { name: 'FA_PROFILE_PAGE_LOADED', description: 'Profile page loaded' },
|
||||
FA_PROFILE_PAGE_BUTTON_CLICKED :{
|
||||
name : 'FA_PROFILE_PAGE_BUTTON_CLICKED',
|
||||
description : 'Click on profile page button on bottom navigation bar',
|
||||
},
|
||||
AV_PROFILE_PAGE_LOGOUT_BUTTON_CLICKED: {
|
||||
name: 'FA_PROFILE_PAGE_LOGOUT_BUTTON_CLICKED',
|
||||
description: 'Logout CTA clicked',
|
||||
@@ -366,6 +378,10 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
name: 'FA_SEND_PAYMENT_LINK_FAILED_LIMIT_REACHED',
|
||||
description: 'FA_SEND_PAYMENT_LINK_FAILED_LIMIT_REACHED',
|
||||
},
|
||||
FA_TOTAL_OUTSTANDING_BREAKUP_LOADED: {
|
||||
name : 'FA_TOTAL_OUTSTANDING_BREAKUP_LOADED',
|
||||
description : 'Outstanding breakup is loaded',
|
||||
},
|
||||
FA_TOTAL_OUTSTANDING_BREAKUP_CLICKED: {
|
||||
name: 'FA_TOTAL_OUTSTANDING_BREAKUP_CLICKED',
|
||||
description: 'FA_TOTAL_OUTSTANDING_BREAKUP_CLICKED',
|
||||
@@ -378,10 +394,19 @@ export const CLICKSTREAM_EVENT_NAMES = {
|
||||
name: 'FA_VIEW_MORE_ADDRESSES_CLICKED',
|
||||
description: 'FA_VIEW_MORE_ADDRESSES_CLICKED',
|
||||
},
|
||||
FA_ADDITIONAL_ADDRESSES_BUTTON_CLICKED : {
|
||||
name : 'FA_ADDITIONAL_ADDRESSES_BUTTON_CLICKED',
|
||||
description: 'Click on additional addresses button in all addresses screen',
|
||||
},
|
||||
|
||||
FA_VIEW_ADDRESSES_FAILED: {
|
||||
name: 'FA_VIEW_ADDRESSES_FAILED',
|
||||
description: 'FA_VIEW_ADDRESSES_FAILED',
|
||||
},
|
||||
FA_VIEW_EMI_SCHEDULE_LOADED : {
|
||||
name: 'FA_VIEW_EMI_SCHEDULE_LOADED',
|
||||
description: 'EMI schedule page is loaded',
|
||||
},
|
||||
FA_VIEW_EMI_SCHEDULE_CLICKED: {
|
||||
name: 'FA_VIEW_EMI_SCHEDULE_CLICKED',
|
||||
description: 'FA_VIEW_EMI_SCHEDULE_CLICKED',
|
||||
|
||||
@@ -8,10 +8,11 @@ interface FloatingBannerCtaProps {
|
||||
onPressHandler: () => void;
|
||||
icon?: JSX.Element;
|
||||
containerStyle?: StyleProp<ViewStyle>;
|
||||
textStyle?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const FloatingBannerCta = (props: FloatingBannerCtaProps) => {
|
||||
const { icon, title, onPressHandler, containerStyle } = props;
|
||||
const { icon, title, onPressHandler, containerStyle, textStyle } = props;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
@@ -19,7 +20,7 @@ const FloatingBannerCta = (props: FloatingBannerCtaProps) => {
|
||||
onPress={onPressHandler}
|
||||
>
|
||||
{icon ? icon : null}
|
||||
<Text style={GenericStyles.pl6}>{title}</Text>
|
||||
<Text style={[GenericStyles.pl6, textStyle ]}>{title}</Text>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -75,6 +75,7 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const appState = useRef(AppState.currentState);
|
||||
const isTeamLead = useAppSelector((state) => state.user.isTeamLead);
|
||||
const deviceId = useAppSelector((state) => state?.user?.deviceId);
|
||||
const caseSyncLock = useAppSelector((state) => state?.user?.caseSyncLock);
|
||||
const lastFirebaseResyncTimestamp = useAppSelector((state) => state?.metadata?.lastFirebaseResyncTimestamp);
|
||||
|
||||
@@ -122,6 +123,7 @@ const TrackingComponent: React.FC<ITrackingComponent> = ({ children }) => {
|
||||
timestamp: Date.now(),
|
||||
isActiveOnApp: Boolean(isActiveOnApp),
|
||||
userActivityOnApp: String(userActivityonApp),
|
||||
deviceId : deviceId,
|
||||
};
|
||||
dispatch(setDeviceGeolocationsBuffer(geolocation));
|
||||
dispatch(sendLocationAndActivenessToServer([geolocation]));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Linking, StyleSheet, TouchableOpacity, View } from 'react-native';
|
||||
import React, { useMemo } from 'react';
|
||||
import { IGeolocation } from '../../../screens/caseDetails/interface';
|
||||
import { GeolocationSource, IGeolocation } from '../../../screens/caseDetails/interface';
|
||||
import { useAppDispatch, useAppSelector } from '../../../hooks';
|
||||
import { getDistanceFromLatLonInKm, getGoogleMapUrl } from '../../utlis/commonFunctions';
|
||||
import Text from '../../../../RN-UI-LIB/src/components/Text';
|
||||
@@ -41,7 +41,7 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
isFeedbackView,
|
||||
handlePageRouting,
|
||||
}) => {
|
||||
const { latitude, longitude, capturedTimestamp, tag, id } = address;
|
||||
const { latitude, longitude, capturedTimestamp, tag, id, primarySource } = address;
|
||||
const { deviceGeolocationCoordinate, prefilledAddressScreenTemplate } = useAppSelector(
|
||||
(state) => ({
|
||||
deviceGeolocationCoordinate: state.foregroundService?.deviceGeolocationCoordinate,
|
||||
@@ -134,7 +134,7 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
{tag}
|
||||
</Text>
|
||||
{roundoffRelativeDistanceBwLatLong ? (
|
||||
<Text>({roundoffRelativeDistanceBwLatLong}km away)</Text>
|
||||
<Text>({roundoffRelativeDistanceBwLatLong} km away)</Text>
|
||||
) : null}
|
||||
</View>
|
||||
<View style={GenericStyles.row}>
|
||||
@@ -145,6 +145,12 @@ const GeolocationAddress: React.FC<IGeolocationAddress> = ({
|
||||
<Text small>{addressTime}</Text>
|
||||
</View>
|
||||
) : null}
|
||||
{(primarySource && primarySource === GeolocationSource.DATA_SUTRAM) ? (
|
||||
<View style={[GenericStyles.row, GenericStyles.alignCenter]}>
|
||||
<View style={styles.circleSeparator} />
|
||||
<Text small>Skip Tracing</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
{!isFeedbackView ? (
|
||||
isFeedbackPresent ? (
|
||||
|
||||
@@ -4,37 +4,37 @@ import { NativeModules } from 'react-native';
|
||||
const { DeviceUtilsModule } = NativeModules; // this is the same name we returned in getName function.
|
||||
|
||||
// returns true if enabled, and false if disabled.
|
||||
export const locationEnabled = (): Promise<boolean> => DeviceUtilsModule?.isLocationEnabled();
|
||||
export const locationEnabled = (): Promise<boolean> => DeviceUtilsModule.isLocationEnabled();
|
||||
|
||||
// returns array of all the installed packages.
|
||||
export const getAllInstalledApp = (): Promise<string> => DeviceUtilsModule?.getAllInstalledApp();
|
||||
export const getAllInstalledApp = (): Promise<string> => DeviceUtilsModule.getAllInstalledApp();
|
||||
|
||||
// export const alfredHandleSWWEvent = (error: Error) => {
|
||||
// const { message = '', stack = '', name = '' } = error;
|
||||
export const alfredHandleSWWEvent = (error: Error) => {
|
||||
const { message = '', stack = '', name = '' } = error;
|
||||
|
||||
// DeviceUtilsModule.handleSWWEvent(message, stack, name);
|
||||
// };
|
||||
DeviceUtilsModule.handleSWWEvent(message, stack, name);
|
||||
};
|
||||
|
||||
// export const handleCrash = () => DeviceUtilsModule.handleCrash();
|
||||
export const handleCrash = () => DeviceUtilsModule.handleCrash();
|
||||
|
||||
// export const handleANR = () => DeviceUtilsModule.handleANR();
|
||||
export const handleANR = () => DeviceUtilsModule.handleANR();
|
||||
|
||||
// export const alfredSetPhoneNumber = (phoneNumber: string) =>
|
||||
// DeviceUtilsModule.setPhoneNumber(phoneNumber);
|
||||
export const alfredSetPhoneNumber = (phoneNumber: string) =>
|
||||
DeviceUtilsModule.setPhoneNumber(phoneNumber);
|
||||
|
||||
// export const alfredSetCodePushVersion = (codePushVersion: string) =>
|
||||
// DeviceUtilsModule.setCodePushVersion(codePushVersion);
|
||||
export const alfredSetCodePushVersion = (codePushVersion: string) =>
|
||||
DeviceUtilsModule.setCodePushVersion(codePushVersion);
|
||||
|
||||
// export const alfredSetUserId = (userId: string) => DeviceUtilsModule.setUserId(userId);
|
||||
export const alfredSetUserId = (userId: string) => DeviceUtilsModule.setUserId(userId);
|
||||
|
||||
// export const sendBottomSheetOpenSignal = (e: boolean) =>
|
||||
// DeviceUtilsModule.sendBottomSheetOpenSignal(e);
|
||||
export const sendBottomSheetOpenSignal = (e: boolean) =>
|
||||
DeviceUtilsModule.sendBottomSheetOpenSignal(e);
|
||||
|
||||
// export const setBottomSheetView = (id: number | null) => DeviceUtilsModule.setBottomSheetView(id);
|
||||
export const setBottomSheetView = (id: number | null) => DeviceUtilsModule.setBottomSheetView(id);
|
||||
|
||||
// export const clearBottomSheet = () => DeviceUtilsModule.clearBottomSheet();
|
||||
export const clearBottomSheet = () => DeviceUtilsModule.clearBottomSheet();
|
||||
|
||||
// export const alfredSetEmailId = (emailId: string) => DeviceUtilsModule.setEmailId(emailId);
|
||||
export const alfredSetEmailId = (emailId: string) => DeviceUtilsModule.setEmailId(emailId);
|
||||
|
||||
// sends content to whatsapp.
|
||||
export const sendContentToWhatsapp = (
|
||||
@@ -46,32 +46,4 @@ export const sendContentToWhatsapp = (
|
||||
): Promise<boolean> =>
|
||||
DeviceUtilsModule?.sendContentToWhatsapp(message, imageUrl, mimeType, format, fileName);
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
export const alfredHandleSWWEvent = (error: Error) => {
|
||||
const { message = '', stack = '', name = '' } = error;
|
||||
|
||||
noop();
|
||||
};
|
||||
|
||||
export const handleCrash = () => noop();
|
||||
|
||||
export const handleANR = () => noop();
|
||||
|
||||
export const alfredSetPhoneNumber = (phoneNumber: string) =>
|
||||
noop();
|
||||
export const alfredSetCodePushVersion = (codePushVersion: string) =>
|
||||
noop();
|
||||
|
||||
export const alfredSetUserId = (userId: string) => noop();
|
||||
|
||||
export const sendBottomSheetOpenSignal = (e: boolean) =>
|
||||
noop();
|
||||
|
||||
export const setBottomSheetView = (id: number | null) => noop();
|
||||
|
||||
export const clearBottomSheet = () => noop();
|
||||
|
||||
export const alfredSetEmailId = (emailId: string) => noop();
|
||||
|
||||
export const getBuildFlavour = (): Promise<buildFlavour> => DeviceUtilsModule.getBuildFlavour();
|
||||
export const getBuildFlavour = (): Promise<buildFlavour> => DeviceUtilsModule.getBuildFlavour();
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface IGeolocationPayload {
|
||||
isActiveOnApp: boolean;
|
||||
userActivityOnApp: string;
|
||||
blacklistedAppsInstalled: Apps[];
|
||||
deviceId : string;
|
||||
}
|
||||
|
||||
export const sendLocationAndActivenessToServer =
|
||||
|
||||
@@ -69,6 +69,7 @@ export interface IUserSlice extends IUser {
|
||||
showAttendanceBanner: boolean;
|
||||
attendanceDate: string;
|
||||
};
|
||||
isAgentPerformanceDashboardVisible: boolean;
|
||||
}
|
||||
|
||||
const initialState: IUserSlice = {
|
||||
@@ -90,6 +91,7 @@ const initialState: IUserSlice = {
|
||||
showAttendanceBanner: true,
|
||||
attendanceDate: '',
|
||||
},
|
||||
isAgentPerformanceDashboardVisible: false,
|
||||
};
|
||||
|
||||
export const userSlice = createSlice({
|
||||
@@ -141,6 +143,9 @@ export const userSlice = createSlice({
|
||||
},
|
||||
setAgentAttendance: (state, action) => {
|
||||
state.agentAttendance = action.payload;
|
||||
},
|
||||
setIsAgentPerformanceDashboardVisible: (state, action) => {
|
||||
state.isAgentPerformanceDashboardVisible = action.payload;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -154,6 +159,7 @@ export const {
|
||||
setIsExternalAgent,
|
||||
setCaseSyncLock,
|
||||
setAgentAttendance,
|
||||
setIsAgentPerformanceDashboardVisible
|
||||
} = userSlice.actions;
|
||||
|
||||
export default userSlice.reducer;
|
||||
|
||||
@@ -375,12 +375,7 @@ export const formatNumberWithSuffix = (number: number): string => {
|
||||
|
||||
export const isAgentDashboardVisible = () => {
|
||||
const user = useAppSelector((state) => state.user);
|
||||
|
||||
const roles = user?.agentRoles;
|
||||
|
||||
const isFieldAgent = roles?.includes(IUserRole.ROLE_FIELD_AGENT);
|
||||
|
||||
return isFieldAgent && roles?.length === 1;
|
||||
return user?.isAgentPerformanceDashboardVisible || false;
|
||||
};
|
||||
|
||||
export const sanatizeSuspisiousFeedback = (feedbackPercent: number) => {
|
||||
|
||||
@@ -1,74 +1,207 @@
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import React from 'react';
|
||||
import { Pressable, SafeAreaView, StyleSheet, View } from 'react-native';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import NaviLogoWithTextIcon from '../../../RN-UI-LIB/src/Icons/NaviLogoWithTextIcon';
|
||||
import Avatar from '../../../RN-UI-LIB/src/components/Avatar';
|
||||
import { GenericStyles, SCREEN_WIDTH } from '../../../RN-UI-LIB/src/styles';
|
||||
import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import { COLORS } from '../../../RN-UI-LIB/src/styles/colors';
|
||||
import { useAppSelector } from '../../hooks';
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||
import { BUSINESS_DATE_FORMAT, dateFormat } from '../../../RN-UI-LIB/src/utlis/dates';
|
||||
import { NAVI_AGENCY_CODE } from '../../common/Constants';
|
||||
import Layout from '@screens/layout/Layout';
|
||||
import NavigationHeader from '@rn-ui-lib/components/NavigationHeader';
|
||||
import { goBack, popToScreen } from '@components/utlis/navigationUtlis';
|
||||
import { getSyncTime } from '@hooks/capturingApi';
|
||||
import { logError } from '@components/utlis/errorUtils';
|
||||
import LineLoader from '@rn-ui-lib/components/suspense_loader/LineLoader';
|
||||
import RetryIcon from '@assets/icons/RetryIcon';
|
||||
import ScreenshotBlocker from '@components/utlis/ScreenshotBlocker';
|
||||
import { getSelfieDocument } from '@actions/profileActions';
|
||||
|
||||
|
||||
const PAGE_TITLE = 'Agent ID card';
|
||||
const backHandler = () => {
|
||||
goBack();
|
||||
};
|
||||
|
||||
|
||||
|
||||
const getTodaysDate = async () => {
|
||||
const timestamp = await getSyncTime();
|
||||
const date = new Date(timestamp);
|
||||
return date;
|
||||
};
|
||||
|
||||
const AgentIdCard = () => {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [retry, setRetry] = useState(false);
|
||||
|
||||
const setLoadingFalse = () => setLoading(false);
|
||||
const setRetryTrue = () => setRetry(true);
|
||||
|
||||
const onRetry = () => {
|
||||
dispatch(getSelfieDocument());
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
ScreenshotBlocker.blockScreenshots();
|
||||
return () => {
|
||||
ScreenshotBlocker.unblockScreenshots();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const [todaysDate, setTodaysDate] = useState(new Date());
|
||||
const fetchTodaysDate = async () => {
|
||||
try {
|
||||
const date = await getTodaysDate();
|
||||
setTodaysDate(date);
|
||||
} catch (error) {
|
||||
logError(error as Error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchTodaysDate();
|
||||
}, [])
|
||||
|
||||
|
||||
|
||||
const {
|
||||
originalImageUri,
|
||||
optimizedImageUri,
|
||||
agentName,
|
||||
agentPhone,
|
||||
validationDate,
|
||||
agencyName,
|
||||
agencyCode,
|
||||
} = useAppSelector((state) => ({
|
||||
originalImageUri: state.profile.originalImageUri,
|
||||
agentName: state.user.user?.name!!,
|
||||
agentPhone: state.user.user?.phoneNumber,
|
||||
validationDate: state.profile.validationDate,
|
||||
agencyName: state.profile.agencyName,
|
||||
agencyCode: state.profile.agencyCode,
|
||||
optimizedImageUri: state.profile.optimizedImageUri,
|
||||
}));
|
||||
|
||||
|
||||
const showRetry = useMemo(() => {
|
||||
return !originalImageUri && !optimizedImageUri;
|
||||
}, [optimizedImageUri, originalImageUri]);
|
||||
|
||||
|
||||
const loaderConf = useMemo(()=>{
|
||||
return [
|
||||
{ width: 75, height: 25, style: { marginTop: 10, marginBottom: 20 } },
|
||||
{ width: 0, height: 0, style: { marginTop: 280 } },
|
||||
{ width: 150, height: 18, style: { marginTop: 15 } },
|
||||
{ width: 200, height: 18, style: { marginTop: 20 } },
|
||||
{ width: 100, height: 18, style: { marginTop: 20 } },
|
||||
]
|
||||
},[])
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<View style={[GenericStyles.p24, GenericStyles.alignCenter, { width: SCREEN_WIDTH - 32 }]}>
|
||||
<NaviLogoWithTextIcon />
|
||||
{agencyName && agencyCode !== NAVI_AGENCY_CODE ? (
|
||||
<>
|
||||
<Text small bold style={styles.greyColor}>
|
||||
in association with
|
||||
</Text>
|
||||
<Text dark bold>
|
||||
{agencyName}
|
||||
</Text>
|
||||
</>
|
||||
) : null}
|
||||
<View style={GenericStyles.mv16}>
|
||||
<Avatar
|
||||
loading={false}
|
||||
size={160}
|
||||
name={agentName}
|
||||
dataURI={originalImageUri}
|
||||
fallbackDataUri={optimizedImageUri}
|
||||
/>
|
||||
</View>
|
||||
<Text small bold style={styles.greyColor}>
|
||||
Valid as of {dateFormat(new Date(validationDate), BUSINESS_DATE_FORMAT)}
|
||||
</Text>
|
||||
<Heading type="h4" dark bold style={GenericStyles.mv4}>
|
||||
{agentName}
|
||||
</Heading>
|
||||
<Text style={GenericStyles.mb4}>Collection agent</Text>
|
||||
<Text light bold>
|
||||
{agentPhone}
|
||||
</Text>
|
||||
</View>
|
||||
<Layout>
|
||||
<SafeAreaView>
|
||||
<NavigationHeader onBack={backHandler} title={PAGE_TITLE} />
|
||||
<View style={[GenericStyles.p24, GenericStyles.alignCenter, styles.container]}>
|
||||
<View style={styles.avatarImage}>
|
||||
<Avatar
|
||||
loading={false}
|
||||
size={280}
|
||||
name={agentName}
|
||||
dataURI={originalImageUri}
|
||||
fallbackDataUri={optimizedImageUri}
|
||||
onSuccess={setLoadingFalse}
|
||||
onErrorFallback={setRetryTrue}
|
||||
/>
|
||||
</View>
|
||||
{loading ? (
|
||||
<>
|
||||
{loaderConf.map((loaderProps, index) => (
|
||||
<>
|
||||
<LineLoader
|
||||
key={index}
|
||||
width={loaderProps.width}
|
||||
height={loaderProps.height}
|
||||
style={[loaderProps.style, styles.lineLoader]}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
{(retry || showRetry && (
|
||||
<View style={styles.retryContainer}>
|
||||
<Pressable
|
||||
style={[GenericStyles.row, GenericStyles.alignCenter]}
|
||||
onPress={onRetry}
|
||||
>
|
||||
<RetryIcon />
|
||||
<Text style={[GenericStyles.ml4, styles.retryText]}>Retry loading ID card</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
)) || null}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<NaviLogoWithTextIcon />
|
||||
{agencyName && agencyCode !== NAVI_AGENCY_CODE ? (
|
||||
<>
|
||||
<Text small bold style={styles.greyColor}>
|
||||
in association with
|
||||
</Text>
|
||||
<Text dark bold>
|
||||
{agencyName}
|
||||
</Text>
|
||||
</>
|
||||
) : null}
|
||||
<View style={styles.avatarMargin}>
|
||||
<Text style={styles.greyColor}>
|
||||
Valid on {dateFormat(new Date(todaysDate), BUSINESS_DATE_FORMAT)}
|
||||
</Text>
|
||||
<Heading type="h4" dark bold style={GenericStyles.mv4}>
|
||||
{agentName}
|
||||
</Heading>
|
||||
<Text style={styles.greyColor}>
|
||||
{agentPhone}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default AgentIdCard;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
...GenericStyles.relative,
|
||||
},
|
||||
greyColor: {
|
||||
color: COLORS.TEXT.GREY,
|
||||
},
|
||||
lineLoader: {
|
||||
borderRadius: 20,
|
||||
},
|
||||
avatarImage: {
|
||||
...GenericStyles.absolute,
|
||||
marginTop: 70,
|
||||
},
|
||||
avatarMargin: {
|
||||
alignItems: 'center',
|
||||
marginTop: 310,
|
||||
},
|
||||
retryContainer: {
|
||||
marginTop: 30,
|
||||
},
|
||||
retryText: {
|
||||
color: COLORS.TEXT.BLUE,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
Linking,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
TouchableHighlight,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
@@ -33,18 +32,16 @@ import CaseItem from '../allCases/CaseItem';
|
||||
import { IUserRole, MY_CASE_ITEM } from '../../reducer/userSlice';
|
||||
import QuestionMarkIcon from '../../assets/icons/QuestionMarkIcon';
|
||||
import IDCardImageCapture from './IDCardImageCapture';
|
||||
import AgentIdCard from './AgentIdCard';
|
||||
import TranslucentModal from '../../../RN-UI-LIB/src/components/TranslucentModal/TranslucentModal';
|
||||
import ArrowSolidIcon from '../../../RN-UI-LIB/src/Icons/ArrowSolidIcon';
|
||||
import { getSelfieDocument } from '../../action/profileActions';
|
||||
import { ImageApprovalStatus } from '../../reducer/profileSlice';
|
||||
import FloatingBannerCta from '@common/FloatingBannerCta';
|
||||
import AttendanceIcon from '@assets/icons/AttendanceIcon';
|
||||
import GoogleFormModal from '@screens/allCases/GoogleFormModal';
|
||||
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
|
||||
|
||||
const Profile: React.FC = () => {
|
||||
const [buttonPressedCount, setButtonPressedCount] = useState(0);
|
||||
const [showIdCard, setShowIdCard] = useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
originalImageUri,
|
||||
@@ -129,16 +126,12 @@ const Profile: React.FC = () => {
|
||||
|
||||
const helpButtonClickHandler = () => Linking.openURL(supportLink);
|
||||
|
||||
const toggleIdCard = () => setShowIdCard((prev) => !prev);
|
||||
|
||||
|
||||
const hideUploadImageBtn =
|
||||
approvalStatus === ImageApprovalStatus.PENDING ||
|
||||
approvalStatus === ImageApprovalStatus.APPROVED;
|
||||
|
||||
const handleViewIdCard = () => {
|
||||
toggleIdCard();
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_ID_CARD_CLICKED);
|
||||
};
|
||||
|
||||
|
||||
const showCompletedCases = !isTeamLead || selectedAgent?.referenceId === MY_CASE_ITEM.referenceId;
|
||||
|
||||
@@ -157,20 +150,22 @@ const Profile: React.FC = () => {
|
||||
showAvatarIcon
|
||||
bottomActionable={
|
||||
originalImageUri && pendingCases?.length ? (
|
||||
<TouchableHighlight
|
||||
onPress={handleViewIdCard}
|
||||
underlayColor={COLORS.HIGHLIGHTER.LIGHT_BUTTON}
|
||||
style={styles.bottomActionable}
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_ID_CARD_CLICKED);
|
||||
navigateToScreen(PageRouteEnum.AGENT_ID_CARD);
|
||||
}}
|
||||
style={styles.bottomActionable}
|
||||
>
|
||||
<View style={[GenericStyles.row, GenericStyles.alignStart]}>
|
||||
<Text small style={styles.whiteText}>
|
||||
View ID card
|
||||
</Text>
|
||||
<View style={{ transform: [{ rotate: '180deg' }] }}>
|
||||
<ArrowSolidIcon fillColor={COLORS.TEXT.WHITE} />
|
||||
<View style={[GenericStyles.row, GenericStyles.alignStart]}>
|
||||
<Text small style={styles.whiteText}>
|
||||
View ID card
|
||||
</Text>
|
||||
<View style={{ transform: [{ rotate: '180deg' }] }}>
|
||||
<ArrowSolidIcon fillColor={COLORS.TEXT.WHITE} />
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
</Pressable>
|
||||
) : null
|
||||
}
|
||||
rightActionable={
|
||||
@@ -280,15 +275,7 @@ const Profile: React.FC = () => {
|
||||
)}
|
||||
<GoogleFormModal showForm={showForm} setShowForm={setShowForm} />
|
||||
|
||||
{pendingCases?.length ? (
|
||||
<TranslucentModal
|
||||
visible={showIdCard}
|
||||
onRequestClose={() => setShowIdCard(false)}
|
||||
flipAnimation
|
||||
>
|
||||
<AgentIdCard />
|
||||
</TranslucentModal>
|
||||
) : null}
|
||||
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -210,11 +210,12 @@ const AddressGeolocation: React.FC<IAddressGeolocation> = ({ route: routeParams
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.7}
|
||||
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
||||
onPress={() =>
|
||||
onPress={() =>{
|
||||
handleRouting(PageRouteEnum.ADDITIONAL_ADDRESSES, {
|
||||
fetchUngroupedAddress, ungroupedAddressFeedbacks
|
||||
})
|
||||
}
|
||||
});
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_ADDITIONAL_ADDRESSES_BUTTON_CLICKED);
|
||||
}}
|
||||
>
|
||||
<Text style={styles.actionBtn}>View all addresses</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from '@hooks';
|
||||
import CasesList from './CasesList';
|
||||
import Text from '../../../RN-UI-LIB/src/components/Text';
|
||||
import { RootState } from '@store';
|
||||
import { initCrashlytics } from '@utils/firebaseUtils';
|
||||
import Layout from '../layout/Layout';
|
||||
@@ -25,13 +24,14 @@ import FullScreenLoaderWrapper from '@common/FullScreenLoaderWrapper';
|
||||
import DashboardIcon from '../../assets/icons/DashboardIcon';
|
||||
import DashBoardScreens from '../Dashboard/DashBoardScreens';
|
||||
import { isAgentDashboardVisible } from '@screens/Dashboard/utils';
|
||||
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { AppState, AppStateStatus, StyleSheet } from 'react-native';
|
||||
import { COLORS } from '@rn-ui-lib/colors';
|
||||
import { GenericStyles } from '@rn-ui-lib/styles';
|
||||
import DailyCommitmentIcon from '@rn-ui-lib/icons/DailyCommitmentIcon';
|
||||
import AddCommitment from '../dailyCommitment/DailyCommitmentBottomSheet';
|
||||
import DailyCommitmentBottomSheet from '../dailyCommitment/DailyCommitmentBottomSheet';
|
||||
import { getVisibilityStatus } from '@screens/dailyCommitment/actions';
|
||||
import { logError } from '@components/utlis/errorUtils';
|
||||
import FloatingBannerCta from '@common/FloatingBannerCta';
|
||||
import { AppStates } from '@interfaces/appStates';
|
||||
|
||||
const AllCasesMain = () => {
|
||||
const { pendingList, pinnedList, completedList, loading } = useAppSelector(
|
||||
@@ -47,42 +47,57 @@ const AllCasesMain = () => {
|
||||
const [isCommitmentFormVisible, setIsCommitmentFormVisible] = useState(false);
|
||||
const [isCommitmentSubmitted, setIsCommitmentSubmitted] = useState(true);
|
||||
|
||||
const handleTabClick = (nextTab: BOTTOM_TAB_ROUTES) => {
|
||||
if (nextTab === BOTTOM_TAB_ROUTES.Dashboard) {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PERFORMANCE_DASHBOARD_BUTTON_CLICKED, {});
|
||||
}
|
||||
else if (nextTab === BOTTOM_TAB_ROUTES.Profile) {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PROFILE_PAGE_BUTTON_CLICKED);
|
||||
}
|
||||
else if (nextTab === BOTTOM_TAB_ROUTES.Cases) {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_CASE_LIST_BUTTON_CLICKED);
|
||||
}
|
||||
else if (nextTab === BOTTOM_TAB_ROUTES.VisitPlan) {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_VISIT_PLAN_BUTTON_CLICKED);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const getVisibility = () => {
|
||||
getVisibilityStatus()
|
||||
.then((response) => {
|
||||
setIsCommitmentSubmitted(response?.isCommitmentFilled);
|
||||
setIsCommitmentFormVisible(response?.isCommitmentBannerVisible);
|
||||
})
|
||||
.catch((err) => {
|
||||
logError(err);
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
getVisibilityStatus()
|
||||
.then((response) => {
|
||||
setIsCommitmentSubmitted(response?.isCommitmentFilled);
|
||||
setIsCommitmentFormVisible(response?.isCommitmentBannerVisible);
|
||||
})
|
||||
.catch((err) => {
|
||||
logError(err);
|
||||
});
|
||||
}, [isCommitmentSubmitted,isCommitmentFormVisible]);
|
||||
getVisibility();
|
||||
}, []);
|
||||
|
||||
const shouldShowBanner = useMemo(() => {
|
||||
return !isTeamLead && !isCommitmentSubmitted && isCommitmentFormVisible;
|
||||
}, [isCommitmentSubmitted, isCommitmentFormVisible, isTeamLead]);
|
||||
return !isCommitmentSubmitted && isCommitmentFormVisible;
|
||||
}, [isCommitmentSubmitted, isCommitmentFormVisible]);
|
||||
|
||||
|
||||
const openCommitmentScreen = () => {
|
||||
setOpenBottomSheet(true);
|
||||
};
|
||||
const CommitmentComponent = () => {
|
||||
return (
|
||||
<>
|
||||
<TouchableOpacity
|
||||
activeOpacity={0.8}
|
||||
style={[GenericStyles.centerAlignedRow, styles.container]}
|
||||
onPress={openCommitmentScreen}
|
||||
>
|
||||
<DailyCommitmentIcon />
|
||||
<Text bold dark style={[GenericStyles.ml8, GenericStyles.mr8, styles.updateText]}>
|
||||
Update your daily commitment
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</>
|
||||
);
|
||||
|
||||
const handleAppStateChange = (nextAppState: AppStateStatus) => {
|
||||
if (nextAppState === AppStates.ACTIVE) {
|
||||
setTimeout(getVisibility, 5000);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
const appStateListener = AppState.addEventListener('change', handleAppStateChange);
|
||||
return () => {
|
||||
appStateListener.remove();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const HOME_SCREENS: ITabScreen[] = useMemo(() => {
|
||||
const bottomSheetScreens = [
|
||||
{
|
||||
@@ -90,7 +105,13 @@ const AllCasesMain = () => {
|
||||
component: () => (
|
||||
<>
|
||||
<CasesList casesList={[...pendingList, ...pinnedList, ...completedList]} allCasesView />
|
||||
{shouldShowBanner ? <CommitmentComponent /> : null}
|
||||
{shouldShowBanner ? <FloatingBannerCta
|
||||
title={"Update your daily commitment"}
|
||||
onPressHandler={openCommitmentScreen}
|
||||
containerStyle={styles.container}
|
||||
icon={<DailyCommitmentIcon />}
|
||||
textStyle={styles.titleText}
|
||||
/> : null}
|
||||
</>
|
||||
),
|
||||
icon: CasesIcon,
|
||||
@@ -102,7 +123,13 @@ const AllCasesMain = () => {
|
||||
component: () => (
|
||||
<>
|
||||
<CasesList casesList={pinnedList} isVisitPlan />
|
||||
{shouldShowBanner ? <CommitmentComponent /> : null}
|
||||
{shouldShowBanner ? <FloatingBannerCta
|
||||
title={"Update your daily commitment"}
|
||||
onPressHandler={openCommitmentScreen}
|
||||
containerStyle={styles.container}
|
||||
icon={<DailyCommitmentIcon />}
|
||||
textStyle={styles.titleText}
|
||||
/> : null}
|
||||
</>
|
||||
),
|
||||
icon: VisitPlanIcon,
|
||||
@@ -115,7 +142,13 @@ const AllCasesMain = () => {
|
||||
component: () => (
|
||||
<>
|
||||
<DashBoardScreens />
|
||||
{shouldShowBanner ? <CommitmentComponent /> : null}
|
||||
{shouldShowBanner ? <FloatingBannerCta
|
||||
title={"Update your daily commitment"}
|
||||
onPressHandler={openCommitmentScreen}
|
||||
containerStyle={styles.container}
|
||||
icon={<DailyCommitmentIcon />}
|
||||
textStyle={styles.titleText}
|
||||
/> : null}
|
||||
</>
|
||||
),
|
||||
icon: DashboardIcon,
|
||||
@@ -127,7 +160,13 @@ const AllCasesMain = () => {
|
||||
component: () => (
|
||||
<>
|
||||
<Profile />
|
||||
{shouldShowBanner ? <CommitmentComponent /> : null}
|
||||
{shouldShowBanner ? <FloatingBannerCta
|
||||
title={"Update your daily commitment"}
|
||||
onPressHandler={openCommitmentScreen}
|
||||
containerStyle={styles.container}
|
||||
icon={<DailyCommitmentIcon />}
|
||||
textStyle={styles.titleText}
|
||||
/> : null}
|
||||
</>
|
||||
),
|
||||
icon: ProfileIcon,
|
||||
@@ -147,8 +186,7 @@ const AllCasesMain = () => {
|
||||
currentTab: getCurrentScreen()?.name,
|
||||
nextTab,
|
||||
});
|
||||
if (nextTab === BOTTOM_TAB_ROUTES.Dashboard)
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_PERFORMANCE_DASHBOARD_BUTTON_CLICKED, {});
|
||||
handleTabClick(nextTab);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -168,7 +206,11 @@ const AllCasesMain = () => {
|
||||
onTabPress={(e) => onTabPressHandler(e)}
|
||||
/>
|
||||
<CasesActionButtons />
|
||||
<AddCommitment openBottomSheet={openBottomSheet} setOpenBottomSheet={setOpenBottomSheet} />
|
||||
{!isCommitmentSubmitted && isCommitmentFormVisible && <DailyCommitmentBottomSheet
|
||||
openBottomSheet={openBottomSheet}
|
||||
setOpenBottomSheet={setOpenBottomSheet}
|
||||
onSuccessCallback={() => { getVisibility();}}
|
||||
/>}
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
@@ -177,8 +219,11 @@ const styles = StyleSheet.create({
|
||||
backgroundColor: COLORS.BACKGROUND.TEAL,
|
||||
height: 40,
|
||||
},
|
||||
updateText: {
|
||||
titleText: {
|
||||
color: COLORS.TEXT.TEAL,
|
||||
marginLeft: 2,
|
||||
marginRight: 8,
|
||||
fontFamily: 'Inter-Bold',
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ function AuthRouter() {
|
||||
}
|
||||
alfredSetCodePushVersion(getAppVersion());
|
||||
NetworkStatusService.listenForOnline(dispatch);
|
||||
}, []);
|
||||
}, [user.user]);
|
||||
|
||||
// for setting user token in global.ts for api calling's
|
||||
setGlobalUserData({
|
||||
|
||||
@@ -21,14 +21,21 @@ import { CaptureGeolocation, DeviceLocation } from '@components/form/services/ge
|
||||
import { setDeviceGeolocation } from '@reducers/foregroundServiceSlice';
|
||||
import NearbyCases from '@screens/allCases/NearbyCases';
|
||||
import usePolling from '@hooks/usePolling';
|
||||
import { getFirestoreResyncIntervalInMinutes } from '@common/AgentActivityConfigurableConstants';
|
||||
import useResyncFirebase from '@hooks/useResyncFirebase';
|
||||
import CaseDetailStack from '@screens/caseDetails/CaseDetailStack';
|
||||
import FullScreenLoader from '@rn-ui-lib/components/FullScreenLoader';
|
||||
import { getFirestoreResyncIntervalInMinutes } from '@common/AgentActivityConfigurableConstants';
|
||||
import AgentIdCard from '@screens/Profile/AgentIdCard';
|
||||
|
||||
const Stack = createNativeStackNavigator();
|
||||
|
||||
export enum PageRouteEnum {
|
||||
HOME = 'Home',
|
||||
CASE_DETAIL_STACK = 'caseDetailStack',
|
||||
TODO_LIST = 'TodoList',
|
||||
COMPLETED_CASES = 'CompletedCases',
|
||||
NOTIFICATIONS = 'Notifications',
|
||||
IMPERSONATED_LOGIN = 'ImpersonatedUserLogin',
|
||||
PAYMENTS = 'registerPayments',
|
||||
ADDRESS_GEO = 'addressGeolocation',
|
||||
NEW_ADDRESS = 'newAddress',
|
||||
@@ -41,6 +48,7 @@ export enum PageRouteEnum {
|
||||
FILTERED_CASES = 'filteredCases',
|
||||
NEARBY_CASES = 'nearbyCases',
|
||||
GEOLOCATION_OLD_FEEDBACKS = 'geolocationOldFeedbacks',
|
||||
AGENT_ID_CARD = 'AgentIdCard',
|
||||
}
|
||||
|
||||
export const DEFAULT_SCREEN_OPTIONS: NativeStackNavigationOptions = {
|
||||
@@ -109,8 +117,8 @@ const ProtectedRouter = () => {
|
||||
screenOptions={DEFAULT_SCREEN_OPTIONS}
|
||||
screenListeners={getScreenFocusListenerObj}
|
||||
>
|
||||
<Stack.Screen name="Home" component={AllCasesMain} />
|
||||
<Stack.Screen name="caseDetailStack" component={CaseDetailStack} />
|
||||
<Stack.Screen name={PageRouteEnum.HOME} component={AllCasesMain} />
|
||||
<Stack.Screen name={PageRouteEnum.CASE_DETAIL_STACK} component={CaseDetailStack} />
|
||||
<Stack.Screen
|
||||
name={PageRouteEnum.NEARBY_CASES}
|
||||
component={NearbyCases}
|
||||
@@ -119,10 +127,11 @@ const ProtectedRouter = () => {
|
||||
animation: 'slide_from_right',
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen name="TodoList" component={TodoList} />
|
||||
<Stack.Screen name="CompletedCases" component={CompletedCase} />
|
||||
<Stack.Screen name="Notifications" component={Notifications} />
|
||||
<Stack.Screen name="ImpersonatedUserLogin" component={ImpersonatedUser} />
|
||||
<Stack.Screen name={PageRouteEnum.TODO_LIST} component={TodoList} />
|
||||
<Stack.Screen name={PageRouteEnum.COMPLETED_CASES} component={CompletedCase} />
|
||||
<Stack.Screen name={PageRouteEnum.NOTIFICATIONS} component={Notifications} />
|
||||
<Stack.Screen name={PageRouteEnum.IMPERSONATED_LOGIN} component={ImpersonatedUser} />
|
||||
<Stack.Screen name={PageRouteEnum.AGENT_ID_CARD} component={AgentIdCard} />
|
||||
</Stack.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ const CaseDetails: React.FC<ICaseDetails> = (props) => {
|
||||
setShowCallingBottomSheet(true);
|
||||
};
|
||||
|
||||
const opacityAnimation = useRef(new Animated.Value(0.8, {useNativeDriver: true})).current;
|
||||
const opacityAnimation = useRef(new Animated.Value(0.8)).current;
|
||||
const slideInUpJourney = useRef(new Animated.Value(5, { useNativeDriver: true })).current;
|
||||
const duration = 300;
|
||||
|
||||
@@ -134,4 +134,4 @@ export const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export default CaseDetails;
|
||||
export default CaseDetails;
|
||||
@@ -151,7 +151,7 @@ export enum DOCUMENT_TYPE {
|
||||
|
||||
export enum LegalDocumentFullName {
|
||||
LDN = 'Loan_Demand_Notice',
|
||||
LRN = 'Loan_Recovery_Notice',
|
||||
LRN = 'Loan_Recall_Notice',
|
||||
}
|
||||
|
||||
export enum DocumentTitle {
|
||||
|
||||
@@ -7,10 +7,7 @@ import { GenericStyles } from '../../../RN-UI-LIB/src/styles';
|
||||
import { Controller, FieldErrors, useForm } from 'react-hook-form';
|
||||
import { isValidAmountEntered } from '../../components/utlis/commonFunctions';
|
||||
import { addCommitmentApi, getTodaysPtpAmount} from './actions';
|
||||
import Heading from '@rn-ui-lib/components/Heading';
|
||||
import DailyCommitmentIcon from '@rn-ui-lib/icons/DailyCommitmentIcon';
|
||||
import BottomSheetWrapper from '@common/BottomSheetWrapper';
|
||||
import CloseIcon from '@rn-ui-lib/icons/CloseIcon';
|
||||
import { COLORS } from '@rn-ui-lib/colors';
|
||||
import { EXAMPLE_VALUES } from './constants';
|
||||
import { useAppDispatch} from '@hooks';
|
||||
@@ -20,7 +17,8 @@ import { IAddCommitment, IAddCommitmentProps } from '@interfaces/commitmentTrack
|
||||
import HeaderComponent from './headerComponent';
|
||||
import { logError } from '@components/utlis/errorUtils';
|
||||
|
||||
const AddCommitment: React.FC<IAddCommitmentProps> = ({ openBottomSheet, setOpenBottomSheet }) => {
|
||||
const DailyCommitmentBottomSheet: React.FC<IAddCommitmentProps> = (
|
||||
{ openBottomSheet, setOpenBottomSheet, onSuccessCallback }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const {
|
||||
control,
|
||||
@@ -32,7 +30,7 @@ const AddCommitment: React.FC<IAddCommitmentProps> = ({ openBottomSheet, setOpen
|
||||
mode: 'onChange',
|
||||
});
|
||||
const [submitErrors, setSubmitErrors] = useState<FieldErrors<IAddCommitment>>({});
|
||||
const [todaysPtpAmount, setTodaysPtpAmount] = useState(1000);
|
||||
const [todaysPtpAmount, setTodaysPtpAmount] = useState(0);
|
||||
useEffect(() => {
|
||||
getTodaysPtpAmount()
|
||||
.then((response) => {
|
||||
@@ -79,9 +77,11 @@ const AddCommitment: React.FC<IAddCommitmentProps> = ({ openBottomSheet, setOpen
|
||||
dispatch(
|
||||
addCommitmentApi(data, () => {
|
||||
setLoading(false);
|
||||
})
|
||||
);
|
||||
onBack();
|
||||
}, () => {
|
||||
onSuccessCallback && onSuccessCallback();
|
||||
onBack();
|
||||
}
|
||||
));
|
||||
};
|
||||
const handleError = (data: FieldErrors<IAddCommitment>) => {
|
||||
setSubmitErrors(data);
|
||||
@@ -218,4 +218,4 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
export default AddCommitment;
|
||||
export default DailyCommitmentBottomSheet;
|
||||
|
||||
@@ -11,18 +11,17 @@ import { addClickstreamEvent } from '@services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants';
|
||||
import { AppDispatch } from '@store';
|
||||
import { IAddCommitment } from '@interfaces/commitmentTracker.types';
|
||||
import { getSyncTime } from '@hooks/capturingApi';
|
||||
import { logError } from '@components/utlis/errorUtils';
|
||||
|
||||
export const getTodaysPtpAmount = async () => {
|
||||
try {
|
||||
const url = getApiUrl(ApiKeys.GET_PTP_AMOUNT);
|
||||
const response = await axiosInstance.get(url);
|
||||
return response?.data;
|
||||
} catch (err) {
|
||||
logError(err as Error, 'Error fetching today\'s PTP amount:');
|
||||
return COMMITMENT_TYPE.EMPTY_PTP_AMOUNT;
|
||||
}
|
||||
try {
|
||||
const url = getApiUrl(ApiKeys.GET_PTP_AMOUNT);
|
||||
const response = await axiosInstance.get(url);
|
||||
return response?.data;
|
||||
} catch (err) {
|
||||
logError(err as Error, 'Error fetching today\'s PTP amount:');
|
||||
return COMMITMENT_TYPE.EMPTY_PTP_AMOUNT;
|
||||
}
|
||||
};
|
||||
|
||||
export const getVisibilityStatus = async () => {
|
||||
@@ -36,10 +35,10 @@ export const getVisibilityStatus = async () => {
|
||||
};
|
||||
|
||||
export const addCommitmentApi =
|
||||
(data: IAddCommitment, afterApiCallback?: GenericFunctionArgs) => async (dispatch: AppDispatch) => {
|
||||
(data: IAddCommitment, afterApiCallback?: GenericFunctionArgs, onSuccessCallback?: GenericFunctionArgs) =>
|
||||
async (dispatch: AppDispatch) => {
|
||||
const { cashCommitted, visitsCommitted } = data;
|
||||
const url = getApiUrl(ApiKeys.DAILY_COMMITMENT);
|
||||
const timestamp = await getSyncTime();
|
||||
const payload = data;
|
||||
axiosInstance
|
||||
.post(url, payload)
|
||||
@@ -49,6 +48,9 @@ export const addCommitmentApi =
|
||||
type: 'info',
|
||||
text1: COMMITMENT_TYPE.COMMITMENT_SUBMITTED_SUCCESSFULLY,
|
||||
});
|
||||
if (typeof afterApiCallback === 'function') {
|
||||
onSuccessCallback && onSuccessCallback();
|
||||
}
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_DAILY_COMMITMENT_SUBMITTED);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import BottomSheet from '../../../RN-UI-LIB/src/components/bottom_sheet/BottomSheet';
|
||||
import Heading from '../../../RN-UI-LIB/src/components/Heading';
|
||||
import CloseIcon from '../../../RN-UI-LIB/src/Icons/CloseIcon';
|
||||
@@ -12,6 +12,8 @@ import { formatAmount } from '../../../RN-UI-LIB/src/utlis/amount';
|
||||
import { getNumberWithRankSuffix } from '../../../RN-UI-LIB/src/utlis/common';
|
||||
import { getDynamicBottomSheetHeightPercentageFn } from '../../components/utlis/commonFunctions';
|
||||
import BottomSheetWrapper from '../../common/BottomSheetWrapper';
|
||||
import { addClickstreamEvent } from '@services/clickstreamEventService';
|
||||
import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants';
|
||||
|
||||
interface IEmiBreakupBottomSheet {
|
||||
openBottomSheet: boolean;
|
||||
@@ -30,6 +32,15 @@ const EmiBreakupBottomSheet: React.FC<IEmiBreakupBottomSheet> = (props) => {
|
||||
totalOverDueAmount,
|
||||
totalUnpaidEmiAmount,
|
||||
} = props;
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if( openBottomSheet) {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_TOTAL_OUTSTANDING_BREAKUP_LOADED);
|
||||
}
|
||||
}, [openBottomSheet]);
|
||||
|
||||
|
||||
const height = getDynamicBottomSheetHeightPercentageFn();
|
||||
return (
|
||||
<BottomSheetWrapper
|
||||
|
||||
@@ -100,6 +100,10 @@ const EmiSchedule: React.FC<IEmiSchedule> = (props) => {
|
||||
onRefresh();
|
||||
}
|
||||
}, [isOnline]);
|
||||
|
||||
useEffect(() => {
|
||||
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_TOTAL_OUTSTANDING_BREAKUP_LOADED);
|
||||
},[]);
|
||||
|
||||
if (!isOnline && !emiData) {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { GenericFunctionArgs } from "@common/GenericTypes";
|
||||
|
||||
export interface IAddCommitmentProps {
|
||||
openBottomSheet: boolean;
|
||||
setOpenBottomSheet: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
onSuccessCallback?: GenericFunctionArgs;
|
||||
}
|
||||
|
||||
export interface IAddCommitment {
|
||||
|
||||
Reference in New Issue
Block a user