diff --git a/native/navigation/invite-link-handler.react.js b/native/invite-links/invite-links-context-provider.react.js rename from native/navigation/invite-link-handler.react.js rename to native/invite-links/invite-links-context-provider.react.js --- a/native/navigation/invite-link-handler.react.js +++ b/native/invite-links/invite-links-context-provider.react.js @@ -10,16 +10,32 @@ verifyInviteLinkActionTypes, } from 'lib/actions/link-actions.js'; import { isLoggedIn } from 'lib/selectors/user-selectors.js'; +import type { SetState } from 'lib/types/hook-types.js'; import { useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils.js'; -import { InviteLinkModalRouteName } from './route-names.js'; +import { InviteLinkModalRouteName } from '../navigation/route-names.js'; import { useSelector } from '../redux/redux-utils.js'; import { useOnFirstLaunchEffect } from '../utils/hooks.js'; -function InviteLinkHandler(): null { +type InviteLinksContextType = { + +setCurrentLinkUrl: SetState, +}; + +const defaultContext = { + setCurrentLinkUrl: () => {}, +}; + +const InviteLinksContext: React.Context = + React.createContext(defaultContext); + +type Props = { + +children: React.Node, +}; +function InviteLinksContextProvider(props: Props): React.Node { + const { children } = props; const [currentLink, setCurrentLink] = React.useState(null); React.useEffect(() => { @@ -93,7 +109,18 @@ })(); }, [currentLink, dispatchActionPromise, loggedIn, navigation, validateLink]); - return null; + const contextValue = React.useMemo( + () => ({ + setCurrentLinkUrl: setCurrentLink, + }), + [], + ); + + return ( + + {children} + + ); } const urlRegex = /invite\/(\S+)$/; @@ -108,4 +135,4 @@ return match?.[1]; } -export default InviteLinkHandler; +export { InviteLinksContext, InviteLinksContextProvider }; diff --git a/native/markdown/markdown-link.react.js b/native/markdown/markdown-link.react.js --- a/native/markdown/markdown-link.react.js +++ b/native/markdown/markdown-link.react.js @@ -4,6 +4,8 @@ import * as React from 'react'; import { Text, Linking, Alert } from 'react-native'; +import { inviteLinkUrl } from 'lib/facts/links.js'; + import { MarkdownContext, type MarkdownContextType, @@ -11,9 +13,10 @@ import { MarkdownSpoilerContext } from './markdown-spoiler-context.js'; import { MessagePressResponderContext } from '../chat/message-press-responder-context.js'; import { TextMessageMarkdownContext } from '../chat/text-message-markdown-context.js'; +import { InviteLinksContext } from '../invite-links/invite-links-context-provider.react.js'; import { normalizeURL } from '../utils/url-utils.js'; -function useDisplayLinkPrompt( +function useHandleLinkClick( inputURL: string, markdownContext: MarkdownContextType, messageKey: ?string, @@ -33,7 +36,13 @@ if (url.length > displayURL.length) { displayURL += '…'; } + + const inviteLinksContext = React.useContext(InviteLinksContext); return React.useCallback(() => { + if (url.startsWith(inviteLinkUrl(''))) { + inviteLinksContext?.setCurrentLinkUrl(url); + return; + } messageKey && setLinkModalActive({ [messageKey]: true }); Alert.alert( 'External link', @@ -44,7 +53,15 @@ ], { cancelable: true, onDismiss }, ); - }, [setLinkModalActive, messageKey, displayURL, onConfirm, onDismiss]); + }, [ + url, + messageKey, + setLinkModalActive, + displayURL, + onDismiss, + onConfirm, + inviteLinksContext, + ]); } type TextProps = React.ElementConfig; @@ -76,7 +93,7 @@ const onPressMessage = messagePressResponderContext?.onPressMessage; - const onPressLink = useDisplayLinkPrompt(target, markdownContext, messageKey); + const onPressLink = useHandleLinkClick(target, markdownContext, messageKey); return ( - {devTools} ); diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -33,6 +33,7 @@ import { SQLiteDataHandler } from './data/sqlite-data-handler.js'; import ErrorBoundary from './error-boundary.react.js'; import InputStateContainer from './input/input-state-container.react.js'; +import { InviteLinksContextProvider } from './invite-links/invite-links-context-provider.react.js'; import LifecycleHandler from './lifecycle/lifecycle-handler.react.js'; import MarkdownContextProvider from './markdown/markdown-context-provider.react.js'; import { filesystemMediaCache } from './media/media-cache.js'; @@ -249,7 +250,9 @@ theme={theme} ref={containerRef} > - + + + );