Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3282287
D9638.id32595.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
D9638.id32595.diff
View Options
diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js
--- a/lib/shared/message-utils.js
+++ b/lib/shared/message-utils.js
@@ -41,7 +41,7 @@
RawReactionMessageInfo,
ReactionMessageInfo,
} from '../types/messages/reaction.js';
-import { type ThreadInfo } from '../types/thread-types.js';
+import type { ThreadInfo } from '../types/thread-types.js';
import type { UserInfos } from '../types/user-types.js';
import {
type EntityText,
@@ -665,8 +665,24 @@
);
}
-function isInvalidPinSource(message: RawMessageInfo | MessageInfo): boolean {
- return !messageSpecs[message.type].canBePinned;
+// Prefer checking isInvalidPinSourceForThread below. This function doesn't
+// check whether the user is attempting to pin a SIDEBAR_SOURCE in the context
+// of its parent thread, so it's not suitable for permission checks. We only
+// use it in the message-fetchers.js code where we don't have access to the
+// RawThreadInfo and don't need to do permission checks.
+function isInvalidPinSource(
+ messageInfo: RawMessageInfo | MessageInfo,
+): boolean {
+ return !messageSpecs[messageInfo.type].canBePinned;
+}
+
+function isInvalidPinSourceForThread(
+ messageInfo: RawMessageInfo | MessageInfo,
+ threadInfo: ThreadInfo,
+): boolean {
+ const isValidPinSource = !isInvalidPinSource(messageInfo);
+ const isFirstMessageInSidebar = threadInfo.sourceMessageID === messageInfo.id;
+ return !isValidPinSource || isFirstMessageInSidebar;
}
function isUnableToBeRenderedIndependently(
@@ -706,5 +722,6 @@
useNextLocalID,
isInvalidSidebarSource,
isInvalidPinSource,
+ isInvalidPinSourceForThread,
isUnableToBeRenderedIndependently,
};
diff --git a/lib/utils/toggle-pin-utils.js b/lib/utils/toggle-pin-utils.js
new file mode 100644
--- /dev/null
+++ b/lib/utils/toggle-pin-utils.js
@@ -0,0 +1,25 @@
+// @flow
+
+import { isInvalidPinSourceForThread } from '../shared/message-utils.js';
+import { threadHasPermission } from '../shared/thread-utils.js';
+import type {
+ ComposableMessageInfo,
+ RobotextMessageInfo,
+} from '../types/message-types.js';
+import { threadPermissions } from '../types/thread-permission-types.js';
+import type { ThreadInfo } from '../types/thread-types.js';
+
+function canToggleMessagePin(
+ messageInfo: ComposableMessageInfo | RobotextMessageInfo,
+ threadInfo: ThreadInfo,
+): boolean {
+ const isValidMessage = !isInvalidPinSourceForThread(messageInfo, threadInfo);
+ const hasManagePinsPermission = threadHasPermission(
+ threadInfo,
+ threadPermissions.MANAGE_PINS,
+ );
+
+ return isValidMessage && hasManagePinsPermission;
+}
+
+export { canToggleMessagePin };
diff --git a/native/chat/message-results-screen.react.js b/native/chat/message-results-screen.react.js
--- a/native/chat/message-results-screen.react.js
+++ b/native/chat/message-results-screen.react.js
@@ -9,7 +9,7 @@
import { messageListData } from 'lib/selectors/chat-selectors.js';
import {
createMessageInfo,
- isInvalidPinSource,
+ isInvalidPinSourceForThread,
} from 'lib/shared/message-utils.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import { useServerCall } from 'lib/utils/action-utils.js';
@@ -77,7 +77,7 @@
item =>
item.itemType === 'message' &&
item.isPinned &&
- !isInvalidPinSource(item.messageInfo),
+ !isInvalidPinSourceForThread(item.messageInfo, threadInfo),
);
// By the nature of using messageListData and passing in
@@ -102,7 +102,7 @@
}
return sortedChatMessageInfoItems.filter(Boolean);
- }, [chatMessageInfos, rawMessageResults]);
+ }, [chatMessageInfos, rawMessageResults, threadInfo]);
const measureCallback = React.useCallback(
(listDataWithHeights: $ReadOnlyArray<ChatMessageItemWithHeight>) => {
diff --git a/native/chat/message.react.js b/native/chat/message.react.js
--- a/native/chat/message.react.js
+++ b/native/chat/message.react.js
@@ -8,6 +8,7 @@
} from 'react-native';
import { messageKey } from 'lib/shared/message-utils.js';
+import { canToggleMessagePin } from 'lib/utils/toggle-pin-utils.js';
import type { ChatNavigationProp } from './chat.react.js';
import MultimediaMessage from './multimedia-message.react.js';
@@ -91,6 +92,11 @@
[focused, item],
);
+ const canTogglePins = React.useMemo(
+ () => canToggleMessagePin(props.item.messageInfo, props.item.threadInfo),
+ [props.item.messageInfo, props.item.threadInfo],
+ );
+
const innerMessageNode = React.useMemo(() => {
if (item.messageShapeType === 'text') {
return (
@@ -101,6 +107,7 @@
focused={focused}
toggleFocus={toggleFocus}
verticalBounds={verticalBounds}
+ canTogglePins={canTogglePins}
shouldDisplayPinIndicator={shouldDisplayPinIndicator}
/>
);
@@ -111,6 +118,7 @@
focused={focused}
toggleFocus={toggleFocus}
verticalBounds={verticalBounds}
+ canTogglePins={canTogglePins}
shouldDisplayPinIndicator={shouldDisplayPinIndicator}
/>
);
@@ -134,6 +142,7 @@
shouldDisplayPinIndicator,
toggleFocus,
verticalBounds,
+ canTogglePins,
]);
const message = React.useMemo(
diff --git a/native/chat/multimedia-message.react.js b/native/chat/multimedia-message.react.js
--- a/native/chat/multimedia-message.react.js
+++ b/native/chat/multimedia-message.react.js
@@ -9,13 +9,9 @@
import * as React from 'react';
import { View } from 'react-native';
-import { isInvalidPinSource, messageKey } from 'lib/shared/message-utils.js';
-import {
- threadHasPermission,
- useCanCreateSidebarFromMessage,
-} from 'lib/shared/thread-utils.js';
+import { messageKey } from 'lib/shared/message-utils.js';
+import { useCanCreateSidebarFromMessage } from 'lib/shared/thread-utils.js';
import type { MediaInfo } from 'lib/types/media-types.js';
-import { threadPermissions } from 'lib/types/thread-permission-types.js';
import ComposedMessage from './composed-message.react.js';
import { InnerMultimediaMessage } from './inner-multimedia-message.react.js';
@@ -45,6 +41,7 @@
+focused: boolean,
+toggleFocus: (messageKey: string) => void,
+verticalBounds: ?VerticalBounds,
+ +canTogglePins: boolean,
+shouldDisplayPinIndicator: boolean,
};
type Props = {
@@ -54,7 +51,6 @@
+overlayContext: ?OverlayContextType,
+chatContext: ?ChatContextType,
+canCreateSidebarFromMessage: boolean,
- +canTogglePins: boolean,
};
type State = {
+clickable: boolean,
@@ -242,13 +238,6 @@
props.item.threadInfo,
props.item.messageInfo,
);
- const canTogglePins =
- !isInvalidPinSource(props.item.messageInfo) &&
- threadHasPermission(
- props.item.threadInfo,
- threadPermissions.MANAGE_PINS,
- ) &&
- props.item.threadInfo.sourceMessageID !== props.item.messageInfo.id;
return (
<MultimediaMessage
@@ -258,7 +247,6 @@
overlayContext={overlayContext}
chatContext={chatContext}
canCreateSidebarFromMessage={canCreateSidebarFromMessage}
- canTogglePins={canTogglePins}
/>
);
});
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
@@ -4,7 +4,7 @@
import * as React from 'react';
import { View } from 'react-native';
-import { isInvalidPinSource, messageKey } from 'lib/shared/message-utils.js';
+import { messageKey } from 'lib/shared/message-utils.js';
import {
threadHasPermission,
useCanCreateSidebarFromMessage,
@@ -51,6 +51,7 @@
+focused: boolean,
+toggleFocus: (messageKey: string) => void,
+verticalBounds: ?VerticalBounds,
+ +canTogglePins: boolean,
+shouldDisplayPinIndicator: boolean,
};
type Props = {
@@ -65,7 +66,6 @@
+isLinkModalActive: boolean,
+isUserProfileBottomSheetActive: boolean,
+canEditMessage: boolean,
- +canTogglePins: boolean,
};
class TextMessage extends React.PureComponent<Props> {
message: ?React.ElementRef<typeof View>;
@@ -291,14 +291,6 @@
useCanEditMessageNative(props.item.threadInfo, props.item.messageInfo) &&
!isThisMessageEdited;
- const canTogglePins =
- !isInvalidPinSource(props.item.messageInfo) &&
- threadHasPermission(
- props.item.threadInfo,
- threadPermissions.MANAGE_PINS,
- ) &&
- props.item.threadInfo.sourceMessageID !== props.item.messageInfo.id;
-
React.useEffect(() => clearMarkdownContextData, [clearMarkdownContextData]);
return (
@@ -310,7 +302,6 @@
isLinkModalActive={isLinkModalActive}
isUserProfileBottomSheetActive={isUserProfileBottomSheetActive}
canEditMessage={canEditMessage}
- canTogglePins={canTogglePins}
/>
);
});
diff --git a/web/modals/chat/message-results-modal.react.js b/web/modals/chat/message-results-modal.react.js
--- a/web/modals/chat/message-results-modal.react.js
+++ b/web/modals/chat/message-results-modal.react.js
@@ -11,7 +11,7 @@
import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js';
import {
createMessageInfo,
- isInvalidPinSource,
+ isInvalidPinSourceForThread,
modifyItemForResultScreen,
} from 'lib/shared/message-utils.js';
import { type ThreadInfo } from 'lib/types/thread-types.js';
@@ -80,7 +80,7 @@
item =>
item.itemType === 'message' &&
item.isPinned &&
- !isInvalidPinSource(item.messageInfo),
+ !isInvalidPinSourceForThread(item.messageInfo, threadInfo),
);
// By the nature of using messageListData and passing in
@@ -105,7 +105,7 @@
}
return sortedChatMessageInfoItems;
- }, [chatMessageInfos, rawMessageResults]);
+ }, [chatMessageInfos, rawMessageResults, threadInfo]);
const modifiedItems = React.useMemo(
() =>
diff --git a/web/utils/tooltip-action-utils.js b/web/utils/tooltip-action-utils.js
--- a/web/utils/tooltip-action-utils.js
+++ b/web/utils/tooltip-action-utils.js
@@ -10,10 +10,7 @@
ChatMessageInfoItem,
} from 'lib/selectors/chat-selectors.js';
import { useCanEditMessage } from 'lib/shared/edit-messages-utils.js';
-import {
- createMessageReply,
- isInvalidPinSource,
-} from 'lib/shared/message-utils.js';
+import { createMessageReply } from 'lib/shared/message-utils.js';
import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js';
import {
threadHasPermission,
@@ -23,6 +20,7 @@
import { threadPermissions } from 'lib/types/thread-permission-types.js';
import type { ThreadInfo } from 'lib/types/thread-types.js';
import { longAbsoluteDate } from 'lib/utils/date-utils.js';
+import { canToggleMessagePin } from 'lib/utils/toggle-pin-utils.js';
import {
type MessageTooltipAction,
@@ -274,10 +272,7 @@
const { pushModal } = useModalContext();
const { messageInfo, isPinned } = item;
- const canTogglePin =
- !isInvalidPinSource(messageInfo) &&
- threadHasPermission(threadInfo, threadPermissions.MANAGE_PINS) &&
- threadInfo.sourceMessageID !== item.messageInfo.id;
+ const canTogglePin = canToggleMessagePin(messageInfo, threadInfo);
const inputState = React.useContext(InputStateContext);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 17, 10:52 AM (20 h, 52 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2518104
Default Alt Text
D9638.id32595.diff (10 KB)
Attached To
Mode
D9638: [lib/web/native] Unify logic to check canTogglePins in web and native tooltips
Attached
Detach File
Event Timeline
Log In to Comment