import React, { useCallback, useEffect } from "react"; import { useConnectionInfo } from "@applicaster/zapp-react-native-utils/reactHooks/connection"; import { usePrevious } from "@applicaster/zapp-react-native-utils/reactHooks/utils"; import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor"; import { useOfflineHandlerProps } from "./hooks"; import { componentsLogger } from "../../Helpers/logger"; import { parseConnectionInfo } from "./utils"; const logger = componentsLogger.addSubsystem("OfflineHandler"); // mirrors NOTIFICATION_TOAST_EVENTS.SHOW_TOAST in // @applicaster/quick-brick-core/App/NotificationToastRenderer/NotificationToastManager // (kept as a literal here since this package must not depend on quick-brick-core) const SHOW_TOAST_EVENT = "showToast"; const OFFLINE_STATUS_TOAST_ID = "offline-status"; type Props = { children?: React.ReactElement; }; const timers = { goingOffline: 5000, goingOnline: 2000, }; export const OfflineHandler = ({ children }: Props) => { const connectionInfo = useConnectionInfo(false); const { online } = parseConnectionInfo(connectionInfo); const prevOnline = usePrevious(online); const emitShowToast = useSubscriberFor(SHOW_TOAST_EVENT); const { message, extraMessage, style } = useOfflineHandlerProps(online); const showOnlineToast = useCallback(() => { logger.log("Device is back online, emit toast"); emitShowToast({ id: OFFLINE_STATUS_TOAST_ID, message, extraMessage, style, timeout: timers.goingOnline, }); }, [emitShowToast, message, extraMessage, style]); const showOfflineToast = useCallback(() => { logger.log("Device went offline, emit toast"); emitShowToast({ id: OFFLINE_STATUS_TOAST_ID, message, extraMessage, style, timeout: timers.goingOffline, }); }, [emitShowToast, message, extraMessage, style]); useEffect(() => { // On mount there is no previous state yet: only surface the offline toast // for a device that starts offline. Don't announce "back online" for a // device that was online to begin with. if (prevOnline === undefined) { if (!online) { showOfflineToast(); } return; } // On subsequent renders, only emit a toast when the online/offline state changes. if (prevOnline !== online) { if (!online) { showOfflineToast(); } else { showOnlineToast(); } } }, [online, prevOnline, showOfflineToast, showOnlineToast]); return children; };