diff --git a/native/chat/chat-tab-bar.react.js b/native/chat/chat-tab-bar.react.js new file mode 100644 --- /dev/null +++ b/native/chat/chat-tab-bar.react.js @@ -0,0 +1,81 @@ +// @flow + +import type { + MaterialTopTabBarProps, + Route, + TabBarItemProps, +} from '@react-navigation/core'; +import { MaterialTopTabBar } from '@react-navigation/material-top-tabs'; +import invariant from 'invariant'; +import * as React from 'react'; +import { View } from 'react-native'; +import { TabBarItem } from 'react-native-tab-view'; + +import { threadSettingsNotificationsCopy } from 'lib/shared/thread-settings-notifications-utils.js'; + +import { + nuxTip, + NUXTipsContext, +} from '../components/nux-tips-context.react.js'; + +const ButtonTitleToTip = Object.freeze({ + [threadSettingsNotificationsCopy.MUTED]: nuxTip.MUTED, + [threadSettingsNotificationsCopy.HOME]: nuxTip.HOME, +}); + +type Props = $ReadOnly<{ + ...TabBarItemProps>, + descriptors: $PropertyType>, 'descriptors'>, +}>; + +function TabBarButton(props: Props) { + const { descriptors, ...innerProps } = props; + const tipsContext = React.useContext(NUXTipsContext); + invariant(tipsContext, 'NUXTipsContext should be defined'); + + const viewRef = React.useRef>(); + const onLayout = React.useCallback(() => { + const button = viewRef.current; + if (!button) { + return; + } + const label = descriptors[innerProps.route.key].options.title; + invariant(label, 'label has to be defined in chat tab bar for NUX to work'); + + const tipType = ButtonTitleToTip[label]; + if (!tipType) { + return; + } + button.measure((x, y, width, height, pageX, pageY) => { + tipsContext.registerTipButton(tipType, { + x, + y, + width, + height, + pageX, + pageY, + }); + }); + }, [descriptors, innerProps.route.key, tipsContext]); + + return ( + + + + ); +} + +export default function TabBarTop( + props: MaterialTopTabBarProps>, +): React.Node { + const { descriptors } = props; + + const renderTabBarItem = React.useCallback( + (innerProps: $ReadOnly<{ ...TabBarItemProps>, key: string }>) => ( + + ), + [descriptors], + ); + + return ; +} 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 @@ -38,6 +38,7 @@ type ChatRouterNavigationHelpers, type ChatRouterNavigationAction, } from './chat-router.js'; +import TabBar from './chat-tab-bar.react.js'; import ComposeSubchannel from './compose-subchannel.react.js'; import ComposeThreadButton from './compose-thread-button.react.js'; import FullScreenThreadMediaGallery from './fullscreen-thread-media-gallery.react.js'; @@ -119,15 +120,21 @@ export type ChatTopTabsNavigationHelpers = MaterialTopTabNavigationHelpers; -const homeChatThreadListOptions = { +const homeChatThreadListOptions: { + title: string, + tabBarIcon: ({ +color: string, ... }) => React$Node, +} = { title: threadSettingsNotificationsCopy.HOME, - tabBarIcon: ({ color }: { +color: string, ... }) => ( + tabBarIcon: ({ color }) => ( ), }; -const backgroundChatThreadListOptions = { +const backgroundChatThreadListOptions: { + title: string, + tabBarIcon: ({ +color: string, ... }) => React$Node, +} = { title: threadSettingsNotificationsCopy.MUTED, - tabBarIcon: ({ color }: { +color: string, ... }) => ( + tabBarIcon: ({ color }) => ( ), }; @@ -156,8 +163,9 @@ }), [tabBarAccent, tabBarBackground], ); + return ( - + ); } + +export { backgroundChatThreadListOptions, homeChatThreadListOptions }; 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 @@ -9,6 +9,7 @@ const nuxTip = Object.freeze({ COMMUNITY_DRAWER: 'community_drawer', MUTED: 'muted', + HOME: 'home', }); export type NUXTip = $Values;