UNPKG

@talkjs/react-native

Version:

Official TalkJS SDK for React Native

198 lines (190 loc) 7.29 kB
"use strict"; import { getNotificationHandler } from './index'; import { hasIdOnly } from './User'; import React, { useMemo, useRef, useState, useEffect, forwardRef, useImperativeHandle, useCallback } from 'react'; import { ON_MESSAGE_EVENT, SESSION, TOKEN_FETCHER_EVENT, UI_MOUNTED_MESSAGE, UNREADS_CHANGE_EVENT, VALID_CREDENTIALS_EVENT, WEBVIEW_ERROR, WEBVIEW_LOADED_MESSAGE } from './constants'; import { WebView } from './WebView'; import { CustomHandlers, TalkHandlers } from './Handlers'; import { Platform, StatusBar } from 'react-native'; import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; const SessionContext = /*#__PURE__*/React.createContext(null); function Session(props, ref) { const webViewRef = useRef(null); const pendingScripts = useRef([]); const isWebViewLoadedRef = useRef(false); const [isHeadless, setIsHeadless] = useState(true); const [disableZoom, setDisableZoom] = useState(false); const [keyboardVerticalOffset, setKeyboardVerticalOffset] = useState(Platform.OS === 'ios' ? 95 : 55 + (StatusBar.currentHeight ?? 35)); const [hideKeyboardAccessoryView, setHideKeyboardAccessoryView] = useState(false); const customHandlers = useMemo(() => new CustomHandlers(), []); useEffect(() => { customHandlers.add(WEBVIEW_LOADED_MESSAGE, () => { isWebViewLoadedRef.current = true; pendingScripts.current.length = 0; // Clear the array. }); }, [customHandlers]); const injectJavaScript = useCallback(javascript => { let result = javascript; if (__DEV__) { result = ` try { ${javascript} } catch (e) { sendToReactNative('${WEBVIEW_ERROR}', e.message); } true;`; } if (isWebViewLoadedRef.current) { // This is undefined when the component is being unmounted. webViewRef.current?.injectJavaScript(result); } else { pendingScripts.current.push(result); } }, [isWebViewLoadedRef, webViewRef]); const talkHandlers = useMemo(() => new TalkHandlers(injectJavaScript), [injectJavaScript]); let hasValidCredentialsResolver; useEffect(() => { customHandlers.add(VALID_CREDENTIALS_EVENT, result => { hasValidCredentialsResolver(result); hasValidCredentialsResolver = undefined; }); // This means that there is a UI present, hence we don't need to be headless customHandlers.add(UI_MOUNTED_MESSAGE, () => setIsHeadless(false)); }, []); const context = useMemo(() => { const me = hasIdOnly(props.me) ? props.me.id : props.me; // If the user passes just a user ID, then we assume they either have // browser synchronization off or they have already created the user some // other way. let userSynchronizationString = ''; if (typeof me !== 'string') { userSynchronizationString = ` ${SESSION}.currentUser.createIfNotExists({ name: ${JSON.stringify(me.name)} }); `; } let tokenFetcherString = ''; if (props.tokenFetcher) { tokenFetcherString = ` window.sessionOptions['tokenFetcher'] = async () => { const tokenFetcherPromise = new Promise((resolve) => { window.tokenFetcherResolve = resolve; }); sendToReactNative('${TOKEN_FETCHER_EVENT}'); return tokenFetcherPromise; }; `; customHandlers.add(TOKEN_FETCHER_EVENT, async () => { const token = await props.tokenFetcher(); webViewRef.current.injectJavaScript(`window.tokenFetcherResolve(${JSON.stringify(token)}); true;`); }); } const javascript = ` if (${SESSION}) { ${SESSION}.destroy(); } window.sessionOptions = { appId: ${JSON.stringify(props.appId)}, me: new Talk.User(${JSON.stringify(me)}), token: ${JSON.stringify(props.token)}, signature: ${JSON.stringify(props.signature)} }; ${tokenFetcherString} ${SESSION} = new Talk.Session(sessionOptions); ${userSynchronizationString} true; `; injectJavaScript(javascript); const session = { appId: props.appId, me: props.me, token: props.token, tokenFetcher: props.tokenFetcher, signature: props.signature }; return { session, customHandlers, talkHandlers, injectJavaScript, setDisableZoom, setKeyboardVerticalOffset, setHideKeyboardAccessoryView }; }, [props.appId, props.me, props.signature, props.token, props.tokenFetcher, injectJavaScript]); useEffect(() => { const notificationHandler = getNotificationHandler(); if (notificationHandler) { // Push notification registration if (props.enablePushNotifications === true) { notificationHandler._getTokenPromise().then(() => { const deviceToken = notificationHandler.deviceToken; if (deviceToken.pushRegistrationId) { injectJavaScript(`${SESSION}.setPushRegistration(${JSON.stringify(deviceToken)});true;`); } }); } else if (props.enablePushNotifications === false) { injectJavaScript(`${SESSION}.clearPushRegistrations(); true;`); } } }, [props.enablePushNotifications, context.session]); useEffect(() => { if (props.onMessage) { const subscription = talkHandlers.add(ON_MESSAGE_EVENT, SESSION, props.onMessage); return () => subscription.unsubscribe(); } return; }, [props.onMessage, context.session, talkHandlers]); useEffect(() => { if (props.onUnreadsChange) { const subscription = talkHandlers.add(UNREADS_CHANGE_EVENT, SESSION, props.onUnreadsChange); return () => subscription.unsubscribe(); } return; }, [props.onUnreadsChange, context.session, talkHandlers]); useImperativeHandle(ref, () => ({ hasValidCredentials() { return new Promise(resolve => { hasValidCredentialsResolver = resolve; injectJavaScript(` ${SESSION}.hasValidCredentials().then((result) => { sendToReactNative('${VALID_CREDENTIALS_EVENT}', result); }); true; `); }); }, clearPushRegistrations() { injectJavaScript(`${SESSION}.clearPushRegistrations(); true;`); }, setPushRegistration(token) { injectJavaScript(` ${SESSION}.setPushRegistration(${JSON.stringify(token)}); true; `); }, unsetPushRegistration(token) { injectJavaScript(` ${SESSION}.unsetPushRegistration(${JSON.stringify(token)}); true; `); } }), [injectJavaScript]); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(WebView, { ref: webViewRef, customHandlers: customHandlers, talkHandlers: talkHandlers, isHeadless: isHeadless, disableZoom: disableZoom, pendingScripts: pendingScripts.current, keyboardVerticalOffset: keyboardVerticalOffset, hideKeyboardAccessoryView: hideKeyboardAccessoryView }), /*#__PURE__*/_jsx(SessionContext.Provider, { value: context, children: props.children })] }); } const forwardedSession = /*#__PURE__*/forwardRef(Session); export { forwardedSession as Session, SessionContext }; //# sourceMappingURL=Session.js.map