Skip to content

Commit 4a2ee07

Browse files
authored
fix(channels): untarget message on click (#4684)
1 parent 46e4df3 commit 4a2ee07

3 files changed

Lines changed: 25 additions & 6 deletions

File tree

js/app/packages/channel/Channel/Channel.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ export function Channel(props: ChannelProps) {
650650
selectedMessageId={selection.selectedId}
651651
onSelectMessage={selectMessage}
652652
onClearSelection={clearSelection}
653+
onClearTarget={releaseSelectionAndTarget}
653654
messageListScopeId={messageListScopeId}
654655
/>
655656
)}

js/app/packages/channel/Thread/ChannelThread.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,21 @@ export function ChannelThread(props: ThreadProps) {
9797
);
9898

9999
const isThreadFocused = () => !!replySelection.selectedId();
100+
101+
// Channel navigation landed on this root message (and not on one of its
102+
// replies).
103+
const isRootNavTargeted = () =>
104+
!!props.targetThreadId &&
105+
props.targetThreadId === props.data().id &&
106+
!props.activeTargetReplyId;
107+
100108
const selectThreadMessage = () => {
109+
// Clicking the navigation-targeted message releases the target instead
110+
// of toggling selection.
111+
if (isRootNavTargeted()) {
112+
props.onClearTarget?.(props.data().id);
113+
return;
114+
}
101115
// On touch devices, we want to block "click to select"
102116
if (isTouchDevice()) return;
103117
if (isSelected() && !isThreadFocused()) {
@@ -110,6 +124,12 @@ export function ChannelThread(props: ThreadProps) {
110124
};
111125

112126
const selectReply = (replyId: string) => {
127+
// Clicking the navigation-targeted reply releases the target instead of
128+
// toggling selection.
129+
if (props.activeTargetReplyId === replyId) {
130+
props.onClearTarget?.(props.data().id);
131+
return;
132+
}
113133
// On touch devices, we want to block "click to select"
114134
if (isTouchDevice()) return;
115135
if (isSelected() && replySelection.selectedId() === replyId) {
@@ -267,12 +287,8 @@ export function ChannelThread(props: ThreadProps) {
267287
selected={isSelected() && !isThreadFocused()}
268288
targeted={
269289
// The unified input's reply is bound to this root, or
270-
// channel navigation landed on it (and not on one of its
271-
// replies).
272-
unifiedReplyBinding()?.boundToRoot ||
273-
(!!props.targetThreadId &&
274-
props.targetThreadId === props.data().id &&
275-
!props.activeTargetReplyId)
290+
// channel navigation landed on it.
291+
unifiedReplyBinding()?.boundToRoot || isRootNavTargeted()
276292
}
277293
/>
278294
</DebugSuspense>

js/app/packages/channel/Thread/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ export type ThreadProps = {
5656
selectedMessageId?: Accessor<string | undefined>;
5757
onSelectMessage?: (messageId: string) => void;
5858
onClearSelection?: () => void;
59+
/** Release the navigation target (clicking the targeted message). */
60+
onClearTarget?: (threadId: string) => void;
5961
messageListScopeId?: string;
6062
isNewestThread?: boolean;
6163
} & ThreadState;

0 commit comments

Comments
 (0)