Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3364339
D5515.id18699.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
12 KB
Referenced Files
None
Subscribers
None
D5515.id18699.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 = {
+ +messageKey: string,
+};
+
+const MessageContext: React.Context<MessageContextType> = React.createContext<MessageContextType>(
+ {
+ messageKey: '',
+ },
+);
+
+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
@@ -25,6 +25,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 { getMessageTooltipKey } from './utils';
@@ -46,7 +47,7 @@
// ChatContext
+chatContext: ?ChatContextType,
// MarkdownContext
- +linkModalActive: boolean,
+ +isLinkModalActive: boolean,
+linkIsBlockingPresses: boolean,
};
class TextMessage extends React.PureComponent<Props> {
@@ -62,7 +63,7 @@
verticalBounds,
overlayContext,
chatContext,
- linkModalActive,
+ isLinkModalActive,
linkIsBlockingPresses,
canCreateSidebarFromMessage,
...viewProps
@@ -71,7 +72,7 @@
let swipeOptions = 'none';
const canReply = this.canReply();
const canNavigateToSidebar = this.canNavigateToSidebar();
- if (linkModalActive) {
+ if (isLinkModalActive) {
swipeOptions = 'none';
} else if (canReply && canNavigateToSidebar) {
swipeOptions = 'both';
@@ -147,6 +148,7 @@
message,
props: { verticalBounds, linkIsBlockingPresses },
} = this;
+
if (!message || !verticalBounds || linkIsBlockingPresses) {
return;
}
@@ -208,33 +210,52 @@
function ConnectedTextMessage(props: BaseProps) {
const overlayContext = React.useContext(OverlayContext);
const chatContext = React.useContext(ChatContext);
+ const markdownContext = React.useContext(MarkdownContext);
+ invariant(markdownContext, 'markdownContext should be set');
+
+ const {
+ linkModalActive,
+ linkPressActive,
+ clearMarkdownContextData,
+ } = markdownContext;
+
+ const key = messageKey(props.item.messageInfo);
+
+ // 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[key] || linkPressActive[key]) ?? false;
+
+ const isLinkModalActive = linkModalActive[key] ?? 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
+ // to access the messageKey so it is 'self-aware'
+ const contextValue = React.useMemo(
+ () => ({
+ messageKey: key,
+ }),
+ [key],
+ );
+
+ React.useEffect(() => clearMarkdownContextData, [clearMarkdownContextData]);
+
return (
- <MarkdownContext.Provider value={markdownContext}>
+ <MessageContext.Provider value={contextValue}>
<TextMessage
{...props}
canCreateSidebarFromMessage={canCreateSidebarFromMessage}
overlayContext={overlayContext}
chatContext={chatContext}
- linkModalActive={linkModalActive}
+ isLinkModalActive={isLinkModalActive}
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,48 @@
+// @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<{
+ [key: string]: boolean,
+ }>({});
+ const [linkPressActive, setLinkPressActive] = React.useState<{
+ [key: string]: boolean,
+ }>({});
+
+ const clearMarkdownContextData = React.useCallback(() => {
+ setLinkModalActive({});
+ setLinkPressActive({});
+ }, []);
+
+ const contextValue = React.useMemo(
+ () => ({
+ setLinkModalActive,
+ linkModalActive,
+ setLinkPressActive,
+ linkPressActive,
+ clearMarkdownContextData,
+ }),
+ [
+ setLinkModalActive,
+ linkModalActive,
+ setLinkPressActive,
+ linkPressActive,
+ clearMarkdownContextData,
+ ],
+ );
+
+ 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<{ [key: string]: boolean }>,
+ +linkModalActive: { [key: string]: boolean },
+ +setLinkPressActive: SetState<{ [key: string]: boolean }>,
+ +linkPressActive: { [key: string]: boolean },
+ +clearMarkdownContextData: () => 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,21 @@
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,
+ messageKey: string,
) {
const setLinkModalActive = markdownContext?.setLinkModalActive;
+ const linkModalActive = markdownContext?.linkModalActive;
const onDismiss = React.useCallback(() => {
- setLinkModalActive?.(false);
- }, [setLinkModalActive]);
+ if (linkModalActive) {
+ setLinkModalActive?.({ ...linkModalActive, [messageKey]: false });
+ }
+ }, [setLinkModalActive, linkModalActive, messageKey]);
const url = normalizeURL(inputURL);
const onConfirm = React.useCallback(() => {
@@ -27,7 +32,9 @@
displayURL += '…';
}
return React.useCallback(() => {
- setLinkModalActive && setLinkModalActive(true);
+ setLinkModalActive &&
+ linkModalActive &&
+ setLinkModalActive({ ...linkModalActive, [messageKey]: true });
Alert.alert(
'External link',
`You sure you want to open this link?\n\n${displayURL}`,
@@ -37,7 +44,14 @@
],
{ cancelable: true, onDismiss },
);
- }, [setLinkModalActive, displayURL, onConfirm, onDismiss]);
+ }, [
+ setLinkModalActive,
+ linkModalActive,
+ messageKey,
+ displayURL,
+ onConfirm,
+ onDismiss,
+ ]);
}
type TextProps = React.ElementConfig<typeof Text>;
@@ -48,15 +62,22 @@
};
function MarkdownLink(props: Props): React.Node {
const markdownContext = React.useContext(MarkdownContext);
+ const messageContext = React.useContext(MessageContext);
+
+ const messageKey = messageContext?.messageKey;
const { target, ...rest } = props;
- const onPressLink = useDisplayLinkPrompt(target, markdownContext);
+ const onPressLink = useDisplayLinkPrompt(target, markdownContext, messageKey);
const setLinkPressActive = markdownContext?.setLinkPressActive;
+ const linkPressActive = markdownContext?.linkPressActive;
+
const androidOnStartShouldSetResponderCapture = React.useCallback(() => {
- setLinkPressActive?.(true);
+ if (linkPressActive) {
+ setLinkPressActive?.({ ...linkPressActive, [messageKey]: true });
+ }
return true;
- }, [setLinkPressActive]);
+ }, [setLinkPressActive, linkPressActive, messageKey]);
const activePressHasMoved = React.useRef(false);
const androidOnResponderMove = React.useCallback(() => {
@@ -68,8 +89,10 @@
onPressLink();
}
activePressHasMoved.current = false;
- setLinkPressActive?.(false);
- }, [onPressLink, setLinkPressActive]);
+ if (linkPressActive) {
+ setLinkPressActive?.({ ...linkPressActive, [messageKey]: false });
+ }
+ }, [onPressLink, setLinkPressActive, linkPressActive, messageKey]);
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
@@ -10,6 +10,7 @@
import TextMessageTooltipModal from '../chat/text-message-tooltip-modal.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';
@@ -103,39 +104,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
Tue, Nov 26, 3:51 AM (16 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2582675
Default Alt Text
D5515.id18699.diff (12 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