Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3374930
D5515.vs18028.id18032.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Referenced Files
None
Subscribers
None
D5515.vs18028.id18032.diff
View Options
diff --git a/native/chat/message-context.react.js b/native/chat/message-context.react.js
new file mode 100644
--- /dev/null
+++ b/native/chat/message-context.react.js
@@ -0,0 +1,15 @@
+// @flow
+
+import * as React from 'react';
+
+export type MessageContextType = {
+ +messageID: string,
+};
+
+const MessageContext: React.Context<MessageContextType> = React.createContext<MessageContextType>(
+ {
+ messageID: '',
+ },
+);
+
+export { MessageContext };
diff --git a/native/chat/text-message.react.js b/native/chat/text-message.react.js
--- a/native/chat/text-message.react.js
+++ b/native/chat/text-message.react.js
@@ -23,6 +23,7 @@
import type { ChatNavigationProp } from './chat.react';
import ComposedMessage from './composed-message.react';
import { InnerTextMessage } from './inner-text-message.react';
+import { MessageContext } from './message-context.react';
import textMessageSendFailed from './text-message-send-failed';
import { textMessageTooltipHeight } from './text-message-tooltip-modal.react';
import { getMessageTooltipKey } from './utils';
@@ -142,6 +143,7 @@
message,
props: { verticalBounds, linkIsBlockingPresses },
} = this;
+
if (!message || !verticalBounds || linkIsBlockingPresses) {
return;
}
@@ -199,24 +201,50 @@
const ConnectedTextMessage: React.ComponentType<BaseProps> = React.memo<BaseProps>(
function ConnectedTextMessage(props: BaseProps) {
const overlayContext = React.useContext(OverlayContext);
+ const markdownContext = React.useContext(MarkdownContext);
+ invariant(markdownContext, 'markdown context should be set');
+
+ const {
+ linkModalActive,
+ linkPressActive,
+ clearMessageData,
+ } = markdownContext;
+
+ const { id } = props.item.messageInfo;
+ invariant(id, 'message ID should exist');
+
+ // We check if there is an ID in the respective
+ // objects - if not, we default to false.
+ // The likely situation where the former statement
+ // evaluates to null is when the thread is opened
+ // for the first time.
+ const linkIsBlockingPresses =
+ (linkModalActive[id] || linkPressActive[id]) ?? false;
- const [linkModalActive, setLinkModalActive] = React.useState(false);
- const [linkPressActive, setLinkPressActive] = React.useState(false);
- const markdownContext = React.useMemo(
- () => ({
- setLinkModalActive,
- setLinkPressActive,
- }),
- [setLinkModalActive, setLinkPressActive],
- );
const canCreateSidebarFromMessage = useCanCreateSidebarFromMessage(
props.item.threadInfo,
props.item.messageInfo,
);
- const linkIsBlockingPresses = linkModalActive || linkPressActive;
+ // We use a MessageContext to allow MarkdownLink
+ // (and MarkdownSpoiler soon) to access
+ // the messageID so it is 'self-aware'
+ const contextValue = React.useMemo(
+ () => ({
+ messageID: id,
+ }),
+ [id],
+ );
+
+ React.useEffect(() => {
+ return () => {
+ // Anything in here is fired on component unmount.
+ id ? clearMessageData(id) : null;
+ };
+ }, [clearMessageData, id]);
+
return (
- <MarkdownContext.Provider value={markdownContext}>
+ <MessageContext.Provider value={contextValue}>
<TextMessage
{...props}
canCreateSidebarFromMessage={canCreateSidebarFromMessage}
@@ -224,7 +252,7 @@
linkModalActive={linkModalActive}
linkIsBlockingPresses={linkIsBlockingPresses}
/>
- </MarkdownContext.Provider>
+ </MessageContext.Provider>
);
},
);
diff --git a/native/markdown/markdown-context-provider.react.js b/native/markdown/markdown-context-provider.react.js
new file mode 100644
--- /dev/null
+++ b/native/markdown/markdown-context-provider.react.js
@@ -0,0 +1,44 @@
+// @flow
+
+import * as React from 'react';
+
+import { MarkdownContext } from './markdown-context.js';
+
+type Props = {
+ +children: React.Node,
+};
+
+function MarkdownContextProvider(props: Props): React.Node {
+ const [linkModalActive, setLinkModalActive] = React.useState<Object>({});
+ const [linkPressActive, setLinkPressActive] = React.useState<Object>({});
+
+ const clearMessageData = React.useCallback(() => {
+ setLinkModalActive({});
+ setLinkPressActive({});
+ }, []);
+
+ const contextValue = React.useMemo(
+ () => ({
+ setLinkModalActive,
+ linkModalActive,
+ setLinkPressActive,
+ linkPressActive,
+ clearMessageData,
+ }),
+ [
+ setLinkModalActive,
+ linkModalActive,
+ setLinkPressActive,
+ linkPressActive,
+ clearMessageData,
+ ],
+ );
+
+ return (
+ <MarkdownContext.Provider value={contextValue}>
+ {props.children}
+ </MarkdownContext.Provider>
+ );
+}
+
+export default MarkdownContextProvider;
diff --git a/native/markdown/markdown-context.js b/native/markdown/markdown-context.js
--- a/native/markdown/markdown-context.js
+++ b/native/markdown/markdown-context.js
@@ -2,9 +2,14 @@
import * as React from 'react';
+import type { SetState } from 'lib/types/hook-types';
+
export type MarkdownContextType = {
- +setLinkModalActive: boolean => void,
- +setLinkPressActive: boolean => void,
+ +setLinkModalActive: SetState<Object>,
+ +linkModalActive: Object,
+ +setLinkPressActive: SetState<Object>,
+ +linkPressActive: Object,
+ +clearMessageData: (messageID: string) => void,
};
const MarkdownContext: React.Context<?MarkdownContextType> = React.createContext<?MarkdownContextType>(
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
@@ -5,16 +5,19 @@
import { normalizeURL } from 'lib/utils/url-utils';
+import { MessageContext } from '../chat/message-context.react';
import { MarkdownContext, type MarkdownContextType } from './markdown-context';
function useDisplayLinkPrompt(
inputURL: string,
markdownContext: ?MarkdownContextType,
+ messageID: string,
) {
const setLinkModalActive = markdownContext?.setLinkModalActive;
+ const linkModalActive = markdownContext?.linkModalActive;
const onDismiss = React.useCallback(() => {
- setLinkModalActive?.(false);
- }, [setLinkModalActive]);
+ setLinkModalActive?.({ ...linkModalActive, [messageID]: false });
+ }, [setLinkModalActive, linkModalActive, messageID]);
const url = normalizeURL(inputURL);
const onConfirm = React.useCallback(() => {
@@ -27,7 +30,8 @@
displayURL += '…';
}
return React.useCallback(() => {
- setLinkModalActive && setLinkModalActive(true);
+ setLinkModalActive &&
+ setLinkModalActive({ ...linkModalActive, [messageID]: true });
Alert.alert(
'External link',
`You sure you want to open this link?\n\n${displayURL}`,
@@ -37,7 +41,14 @@
],
{ cancelable: true, onDismiss },
);
- }, [setLinkModalActive, displayURL, onConfirm, onDismiss]);
+ }, [
+ setLinkModalActive,
+ linkModalActive,
+ messageID,
+ displayURL,
+ onConfirm,
+ onDismiss,
+ ]);
}
type TextProps = React.ElementConfig<typeof Text>;
@@ -48,15 +59,20 @@
};
function MarkdownLink(props: Props): React.Node {
const markdownContext = React.useContext(MarkdownContext);
+ const messageContext = React.useContext(MessageContext);
+
+ const messageID = messageContext?.messageID;
const { target, ...rest } = props;
- const onPressLink = useDisplayLinkPrompt(target, markdownContext);
+ const onPressLink = useDisplayLinkPrompt(target, markdownContext, messageID);
const setLinkPressActive = markdownContext?.setLinkPressActive;
+ const linkPressActive = markdownContext?.linkPressActive;
+
const androidOnStartShouldSetResponderCapture = React.useCallback(() => {
- setLinkPressActive?.(true);
+ setLinkPressActive?.({ ...linkPressActive, [messageID]: true });
return true;
- }, [setLinkPressActive]);
+ }, [setLinkPressActive, linkPressActive, messageID]);
const activePressHasMoved = React.useRef(false);
const androidOnResponderMove = React.useCallback(() => {
@@ -68,8 +84,8 @@
onPressLink();
}
activePressHasMoved.current = false;
- setLinkPressActive?.(false);
- }, [onPressLink, setLinkPressActive]);
+ setLinkPressActive?.({ ...linkPressActive, [messageID]: false });
+ }, [onPressLink, setLinkPressActive, linkPressActive, messageID]);
if (Platform.OS !== 'android') {
return <Text onPress={onPressLink} {...rest} />;
diff --git a/native/navigation/app-navigator.react.js b/native/navigation/app-navigator.react.js
--- a/native/navigation/app-navigator.react.js
+++ b/native/navigation/app-navigator.react.js
@@ -21,6 +21,7 @@
import SWMansionIcon from '../components/swmansion-icon.react';
import { type SQLiteContextType, SQLiteContext } from '../data/sqlite-context';
import KeyboardStateContainer from '../keyboard/keyboard-state-container.react';
+import MarkdownContextProvider from '../markdown/markdown-context-provider.react';
import CameraModal from '../media/camera-modal.react';
import ImageModal from '../media/image-modal.react';
import VideoPlaybackModal from '../media/video-playback-modal.react';
@@ -212,39 +213,41 @@
}
return (
<KeyboardStateContainer>
- <App.Navigator>
- <App.Screen name={TabNavigatorRouteName} component={TabNavigator} />
- <App.Screen name={ImageModalRouteName} component={ImageModal} />
- <App.Screen
- name={MultimediaMessageTooltipModalRouteName}
- component={MultimediaMessageTooltipModal}
- />
- <App.Screen
- name={ActionResultModalRouteName}
- component={ActionResultModal}
- />
- <App.Screen
- name={TextMessageTooltipModalRouteName}
- component={TextMessageTooltipModal}
- />
- <App.Screen
- name={ThreadSettingsMemberTooltipModalRouteName}
- component={ThreadSettingsMemberTooltipModal}
- />
- <App.Screen
- name={RelationshipListItemTooltipModalRouteName}
- component={RelationshipListItemTooltipModal}
- />
- <App.Screen
- name={RobotextMessageTooltipModalRouteName}
- component={RobotextMessageTooltipModal}
- />
- <App.Screen name={CameraModalRouteName} component={CameraModal} />
- <App.Screen
- name={VideoPlaybackModalRouteName}
- component={VideoPlaybackModal}
- />
- </App.Navigator>
+ <MarkdownContextProvider>
+ <App.Navigator>
+ <App.Screen name={TabNavigatorRouteName} component={TabNavigator} />
+ <App.Screen name={ImageModalRouteName} component={ImageModal} />
+ <App.Screen
+ name={MultimediaMessageTooltipModalRouteName}
+ component={MultimediaMessageTooltipModal}
+ />
+ <App.Screen
+ name={ActionResultModalRouteName}
+ component={ActionResultModal}
+ />
+ <App.Screen
+ name={TextMessageTooltipModalRouteName}
+ component={TextMessageTooltipModal}
+ />
+ <App.Screen
+ name={ThreadSettingsMemberTooltipModalRouteName}
+ component={ThreadSettingsMemberTooltipModal}
+ />
+ <App.Screen
+ name={RelationshipListItemTooltipModalRouteName}
+ component={RelationshipListItemTooltipModal}
+ />
+ <App.Screen
+ name={RobotextMessageTooltipModalRouteName}
+ component={RobotextMessageTooltipModal}
+ />
+ <App.Screen name={CameraModalRouteName} component={CameraModal} />
+ <App.Screen
+ name={VideoPlaybackModalRouteName}
+ component={VideoPlaybackModal}
+ />
+ </App.Navigator>
+ </MarkdownContextProvider>
{pushHandler}
</KeyboardStateContainer>
);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 27, 5:23 PM (16 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2591171
Default Alt Text
D5515.vs18028.id18032.diff (11 KB)
Attached To
Mode
D5515: [native] Update the existing Context API for Markdown to encompass AppNavigator
Attached
Detach File
Event Timeline
Log In to Comment