Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F32200843
D5515.1765109818.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D5515.1765109818.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,13 @@
+// @flow
+
+import * as React from 'react';
+
+export type MessageContextType = {
+ +messageID: string,
+};
+
+const MessageContext: React.Context<?MessageContextType> = React.createContext<?MessageContextType>(
+ null,
+);
+
+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';
@@ -49,6 +50,8 @@
class TextMessage extends React.PureComponent<Props> {
message: ?React.ElementRef<typeof View>;
+ static contextType = MarkdownContext;
+
render() {
const {
item,
@@ -140,8 +143,18 @@
const {
message,
- props: { verticalBounds, linkIsBlockingPresses },
+ props: { verticalBounds },
} = this;
+
+ let { linkIsBlockingPresses } = this.props;
+
+ /* We run an "updated check" against the Context to check whether the
+ specific message should be blocked from the tooltip appearing */
+ const { messagesLinkModalActive, messagesLinkPressActive } = this.context;
+ linkIsBlockingPresses =
+ messagesLinkModalActive.get(this.props.item.messageInfo.id) ||
+ messagesLinkPressActive.get(this.props.item.messageInfo.id);
+
if (!message || !verticalBounds || linkIsBlockingPresses) {
return;
}
@@ -200,23 +213,65 @@
function ConnectedTextMessage(props: BaseProps) {
const overlayContext = React.useContext(OverlayContext);
- const [linkModalActive, setLinkModalActive] = React.useState(false);
- const [linkPressActive, setLinkPressActive] = React.useState(false);
- const markdownContext = React.useMemo(
- () => ({
- setLinkModalActive,
- setLinkPressActive,
- }),
- [setLinkModalActive, setLinkPressActive],
- );
+ /* We get the Markdown Context */
+ const markdownContext = React.useContext(MarkdownContext);
+ invariant(markdownContext, 'should be set');
+
+ /* Extract the methods & maps */
+ const {
+ setLinkModalActive,
+ setLinkPressActive,
+ clearMessageData,
+ messagesLinkModalActive,
+ messagesLinkPressActive,
+ } = markdownContext;
+
+ /* Extract the messageID */
+ const { id } = props.item.messageInfo;
+ invariant(id, 'should exist');
+
+ /* Set `linkModalActive` & `linkPressActive` to either the
+ value inside the map, or if it does
+ not exist, defualt to false There most likely
+ is not a value for the message if the thread has
+ just been opened */
+ const linkModalActive = messagesLinkModalActive.get(id) ?? false;
+ const linkPressActive = messagesLinkPressActive.get(id) ?? false;
+ setLinkModalActive(id, linkModalActive);
+ setLinkPressActive(id, linkPressActive);
+
+ /* Same logic is before to check if linkIsBlockingPresses */
+ const linkIsBlockingPresses = linkModalActive || linkPressActive;
+
+ /* Not relevant for Markdown refactoring */
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],
+ );
+
+ /* This is how we want to check if the component is
+ unmounted (a specific message),
+ and thus we will clear the data for that message stored
+ in the Context maps */
+ 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 +279,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,49 @@
+// @flow
+
+import * as React from 'react';
+
+import { MarkdownContext } from './markdown-context.js';
+
+type Props = {
+ +children: React.Node,
+};
+
+function MarkdownContextProvider(props: Props): React.Node {
+ const messagesLinkModalActive = React.useRef<Map<string, boolean>>(new Map());
+ const setLinkModalActive = React.useCallback(
+ (messageID: string, active: boolean) =>
+ messagesLinkModalActive.current.set(messageID, active),
+ [],
+ );
+
+ const messagesLinkPressActive = React.useRef<Map<string, boolean>>(new Map());
+ const setLinkPressActive = React.useCallback(
+ (messageID: string, active: boolean) =>
+ messagesLinkPressActive.current.set(messageID, active),
+ [],
+ );
+
+ const clearMessageData = React.useCallback((messageID: string) => {
+ messagesLinkModalActive.current.delete(messageID);
+ messagesLinkPressActive.current.delete(messageID);
+ }, []);
+
+ const contextValue = React.useMemo(
+ () => ({
+ setLinkModalActive,
+ setLinkPressActive,
+ clearMessageData,
+ messagesLinkModalActive: messagesLinkModalActive.current,
+ messagesLinkPressActive: messagesLinkPressActive.current,
+ }),
+ [setLinkModalActive, setLinkPressActive, 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
@@ -3,8 +3,11 @@
import * as React from 'react';
export type MarkdownContextType = {
- +setLinkModalActive: boolean => void,
- +setLinkPressActive: boolean => void,
+ +setLinkModalActive: (messageID: string, active: boolean) => mixed,
+ +setLinkPressActive: (messageID: string, active: boolean) => mixed,
+ +clearMessageData: (messageID: string) => void,
+ +messagesLinkModalActive: $ReadOnlyMap<string, boolean>,
+ +messagesLinkPressActive: $ReadOnlyMap<string, boolean>,
};
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,18 @@
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 onDismiss = React.useCallback(() => {
- setLinkModalActive?.(false);
- }, [setLinkModalActive]);
+ setLinkModalActive?.(messageID, false);
+ }, [setLinkModalActive, messageID]);
const url = normalizeURL(inputURL);
const onConfirm = React.useCallback(() => {
@@ -27,7 +29,8 @@
displayURL += '…';
}
return React.useCallback(() => {
- setLinkModalActive && setLinkModalActive(true);
+ console.log('`MarkdownLink` messageID: ', messageID);
+ setLinkModalActive && setLinkModalActive(messageID, true);
Alert.alert(
'External link',
`You sure you want to open this link?\n\n${displayURL}`,
@@ -37,7 +40,7 @@
],
{ cancelable: true, onDismiss },
);
- }, [setLinkModalActive, displayURL, onConfirm, onDismiss]);
+ }, [setLinkModalActive, messageID, displayURL, onConfirm, onDismiss]);
}
type TextProps = React.ElementConfig<typeof Text>;
@@ -48,15 +51,18 @@
};
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 androidOnStartShouldSetResponderCapture = React.useCallback(() => {
- setLinkPressActive?.(true);
+ setLinkPressActive?.(messageID, true);
return true;
- }, [setLinkPressActive]);
+ }, [setLinkPressActive, messageID]);
const activePressHasMoved = React.useRef(false);
const androidOnResponderMove = React.useCallback(() => {
@@ -68,8 +74,8 @@
onPressLink();
}
activePressHasMoved.current = false;
- setLinkPressActive?.(false);
- }, [onPressLink, setLinkPressActive]);
+ setLinkPressActive?.(messageID, false);
+ }, [onPressLink, setLinkPressActive, 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
Sun, Dec 7, 12:16 PM (18 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5844147
Default Alt Text
D5515.1765109818.diff (13 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