diff --git a/native/chat/chat-thread-list.react.js b/native/chat/chat-thread-list.react.js --- a/native/chat/chat-thread-list.react.js +++ b/native/chat/chat-thread-list.react.js @@ -44,6 +44,7 @@ ChatTopTabsNavigationProp, } from './chat.react.js'; import { useNavigateToThread } from './message-list-types.js'; +import { NUXHandler } from '../components/nux-handler.react.js'; import { BackgroundChatThreadListRouteName, HomeChatThreadListRouteName, @@ -387,6 +388,7 @@ ref={flatListRef} /> {floatingAction} + ), [ diff --git a/native/components/nux-handler.react.js b/native/components/nux-handler.react.js new file mode 100644 --- /dev/null +++ b/native/components/nux-handler.react.js @@ -0,0 +1,52 @@ +// @flow + +import { useNavigation } from '@react-navigation/core'; +import invariant from 'invariant'; +import * as React from 'react'; + +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; + +import { + firstNUXTipKey, + NUXTipsContext, + getNUXTipParams, +} from './nux-tips-context.react.js'; +import type { NUXTipRouteNames } from '../navigation/route-names.js'; +import { useSelector } from '../redux/redux-utils.js'; +import { useOnFirstLaunchEffect } from '../utils/hooks.js'; + +function NUXHandler(): React.Node { + const nuxTipsContext = React.useContext(NUXTipsContext); + invariant(nuxTipsContext, 'nuxTipsContext should be defined'); + const { getTipsProps } = nuxTipsContext; + + const loggedIn = useSelector(isLoggedIn); + + if (!getTipsProps() || !loggedIn) { + return null; + } + + return ; +} + +function NUXHandlerInner(): React.Node { + const navigation = useNavigation(); + + const effect = React.useCallback(() => { + const { nextTip, tooltipLocation, nextRouteName } = + getNUXTipParams(firstNUXTipKey); + invariant(nextRouteName && nextTip, 'first nux tip should be defined'); + + navigation.navigate({ + name: nextRouteName, + params: { + tipKey: nextTip, + tooltipLocation, + }, + }); + }, [navigation]); + + useOnFirstLaunchEffect('NUX_HANDLER', effect); +} + +export { NUXHandler }; diff --git a/native/components/nux-tips-context.react.js b/native/components/nux-tips-context.react.js --- a/native/components/nux-tips-context.react.js +++ b/native/components/nux-tips-context.react.js @@ -4,8 +4,11 @@ import { values } from 'lib/utils/objects.js'; +import { + CommunityDrawerTipRouteName, + MutedTabTipRouteName, +} from '../navigation/route-names.js'; import type { NUXTipRouteNames } from '../navigation/route-names.js'; -import { MutedTabTipRouteName } from '../navigation/route-names.js'; const nuxTip = Object.freeze({ COMMUNITY_DRAWER: 'community_drawer', @@ -21,7 +24,15 @@ +nextRouteName: ?NUXTipRouteNames, }; -const nuxTipParams: { [NUXTip]: NUXTipParams } = { +const firstNUXTipKey = 'firstTip'; +type NUXTipParamsKeys = NUXTip | 'firstTip'; + +const nuxTipParams: { [NUXTipParamsKeys]: NUXTipParams } = { + [firstNUXTipKey]: { + nextTip: nuxTip.COMMUNITY_DRAWER, + tooltipLocation: 'below', + nextRouteName: CommunityDrawerTipRouteName, + }, [nuxTip.COMMUNITY_DRAWER]: { nextTip: nuxTip.MUTED, tooltipLocation: 'below', @@ -34,7 +45,7 @@ }, }; -function getNUXTipParams(currentTipKey: NUXTip): NUXTipParams { +function getNUXTipParams(currentTipKey: NUXTipParamsKeys): NUXTipParams { return nuxTipParams[currentTipKey]; } @@ -62,11 +73,17 @@ function NUXTipsContextProvider(props: Props): React.Node { const { children } = props; - const tipsProps = React.useRef<{ [tip: NUXTip]: ?TipProps }>({}); + const [tipsProps, setTipsProps] = React.useState<{ + [tip: NUXTip]: ?TipProps, + }>(() => ({})); const registerTipButton = React.useCallback( (type: NUXTip, tipProps: ?TipProps) => { - tipsProps.current[type] = tipProps; + setTipsProps(currentTipsProps => { + const newTipsProps = { ...currentTipsProps }; + newTipsProps[type] = tipProps; + return newTipsProps; + }); }, [], ); @@ -74,14 +91,14 @@ const getTipsProps = React.useCallback(() => { const result: { [tip: NUXTip]: TipProps } = {}; for (const type of values(nuxTip)) { - if (!tipsProps.current[type]) { + if (!tipsProps[type]) { return null; } - result[type] = tipsProps.current[type]; + result[type] = tipsProps[type]; } return result; - }, []); + }, [tipsProps]); const value = React.useMemo( () => ({ @@ -96,4 +113,10 @@ ); } -export { NUXTipsContext, NUXTipsContextProvider, nuxTip, getNUXTipParams }; +export { + NUXTipsContext, + NUXTipsContextProvider, + nuxTip, + getNUXTipParams, + firstNUXTipKey, +};