diff --git a/native/chat/chat.react.js b/native/chat/chat.react.js
--- a/native/chat/chat.react.js
+++ b/native/chat/chat.react.js
@@ -55,6 +55,7 @@
import ThreadSettingsButton from './thread-settings-button.react.js';
import ThreadSettingsHeaderTitle from './thread-settings-header-title.react.js';
import KeyboardAvoidingView from '../components/keyboard-avoiding-view.react.js';
+import { NUXHandler } from '../components/nux-handler.react.js';
import {
nuxTip,
NUXTipsContext,
@@ -536,6 +537,7 @@
+
{draftUpdater}
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 { tipsProps } = nuxTipsContext;
+
+ const loggedIn = useSelector(isLoggedIn);
+
+ if (!tipsProps || !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];
}
@@ -49,7 +60,7 @@
export type NUXTipsContextType = {
+registerTipButton: (type: NUXTip, tipProps: ?TipProps) => void,
- +getTipsProps: () => ?{ +[type: NUXTip]: TipProps },
+ +tipsProps: ?{ +[type: NUXTip]: TipProps },
};
const NUXTipsContext: React.Context =
@@ -62,33 +73,39 @@
function NUXTipsContextProvider(props: Props): React.Node {
const { children } = props;
- const tipsProps = React.useRef<{ [tip: NUXTip]: ?TipProps }>({});
+ const [tipsPropsState, setTipsPropsState] = React.useState<{
+ +[tip: NUXTip]: ?TipProps,
+ }>(() => ({}));
const registerTipButton = React.useCallback(
(type: NUXTip, tipProps: ?TipProps) => {
- tipsProps.current[type] = tipProps;
+ setTipsPropsState(currenttipsPropsState => {
+ const newtipsPropsState = { ...currenttipsPropsState };
+ newtipsPropsState[type] = tipProps;
+ return newtipsPropsState;
+ });
},
[],
);
- const getTipsProps = React.useCallback(() => {
+ const tipsProps = React.useMemo(() => {
const result: { [tip: NUXTip]: TipProps } = {};
for (const type of values(nuxTip)) {
- if (!tipsProps.current[type]) {
+ if (!tipsPropsState[type]) {
return null;
}
- result[type] = tipsProps.current[type];
+ result[type] = tipsPropsState[type];
}
return result;
- }, []);
+ }, [tipsPropsState]);
const value = React.useMemo(
() => ({
registerTipButton,
- getTipsProps,
+ tipsProps,
}),
- [getTipsProps, registerTipButton],
+ [tipsProps, registerTipButton],
);
return (
@@ -96,4 +113,10 @@
);
}
-export { NUXTipsContext, NUXTipsContextProvider, nuxTip, getNUXTipParams };
+export {
+ NUXTipsContext,
+ NUXTipsContextProvider,
+ nuxTip,
+ getNUXTipParams,
+ firstNUXTipKey,
+};
diff --git a/native/tooltip/nux-tips-overlay.react.js b/native/tooltip/nux-tips-overlay.react.js
--- a/native/tooltip/nux-tips-overlay.react.js
+++ b/native/tooltip/nux-tips-overlay.react.js
@@ -129,7 +129,7 @@
const { navigation, route } = props;
const { initialCoordinates, verticalBounds } = React.useMemo(() => {
- const tipsProps = nuxTipContext?.getTipsProps();
+ const tipsProps = nuxTipContext?.tipsProps;
invariant(tipsProps, 'tips props should be defined in nux tips overlay');
const { pageX, pageY, width, height } = tipsProps[route.params.tipKey];