@applicaster/zapp-react-native-app
Version:
Zapp App Component for Applicaster's Quick Brick React Native App
124 lines (99 loc) • 3.65 kB
JavaScript
import * as React from "react";
import { BackHandler } from "react-native";
import * as R from "ramda";
import {
QUICK_BRICK_EVENTS,
sendQuickBrickEvent,
} from "@applicaster/zapp-react-native-bridge/QuickBrick";
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
import { useAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils";
import { useRivers } from "@applicaster/zapp-react-native-utils/reactHooks/state";
import { useErrorStore } from "@applicaster/quick-brick-core/App/ErrorBoundary/store";
import { isApplePlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
const getHome = R.compose(R.find(R.propEq("home", true)), R.values);
const isIOS = isApplePlatform();
/* Set to `false` in production, do not commit this change */
const IS_DEBUGGER_ENABLED = false;
/**
* This is a workaround to fix an error on start when debugger is connected.
* Update function body for this function `callNativeSyncHook`
* node_modules/react-native/Libraries/BatchedBridge/MessageQueue.js:167
this.processCallbacks(moduleID, methodID, params, onFail, onSucc);
if(global.nativeCallSyncHook) {
return global.nativeCallSyncHook(moduleID, methodID, params);
}
*/
// Assign this to a dev-only button or useEffect call
const connectToRemoteDebugger = () => {
if (__DEV__ && isIOS) {
try {
const { DevSettings, NativeModules } = require("react-native");
// eslint-disable-next-line no-console
console.warn(`Debugger connected: ${IS_DEBUGGER_ENABLED}`);
if (DevSettings?.setIsDebuggingRemotely) {
DevSettings.setIsDebuggingRemotely(IS_DEBUGGER_ENABLED);
}
NativeModules?.DevSettings?.setIsDebuggingRemotely?.(IS_DEBUGGER_ENABLED);
} catch (error) {
// eslint-disable-next-line no-console
console.error(`connectToRemoteDebugger message: ${error.message}`);
}
}
};
const InteractionManagerComponent = () => {
const { sendHardwareBackButtonClickEvent } = useAnalytics();
const rivers = useRivers();
const navigator = useNavigation();
const isHomeScreen = () => {
const homeId = R.compose(R.prop("id"), getHome)(rivers);
const homePath = `/river/${homeId}`;
return homePath === navigator.currentRoute;
};
const exitToBackground = () => {
sendQuickBrickEvent(QUICK_BRICK_EVENTS.MOVE_APP_TO_BACKGROUND, {
MOVE_APP_TO_BACKGROUND: true,
});
};
const goToHome = () => {
const home = getHome(rivers);
if (!home) {
throw new Error("Could not find home screen");
}
navigator.replace(home);
};
const onHardwareBackPress = React.useCallback(() => {
if (navigator && !navigator.canGoBack()) {
if (isHomeScreen()) {
exitToBackground();
} else {
try {
goToHome();
} catch (e) {
const errorMessage = "Can't find home screen";
const error = new Error(errorMessage);
useErrorStore
.getState()
.setError(error, "Failed navigating to home screen", false);
}
}
} else {
sendHardwareBackButtonClickEvent({ navigator });
navigator.goBack();
}
return true; // Take care! see jsdoc above
}, [navigator.currentRoute]);
React.useEffect(() => {
connectToRemoteDebugger();
}, []);
React.useEffect(() => {
const unsubscribe = BackHandler.addEventListener(
"hardwareBackPress",
onHardwareBackPress
);
return () => {
unsubscribe.remove();
};
}, [onHardwareBackPress]);
return null;
};
export const InteractionManager = React.memo(InteractionManagerComponent);