Comments: Fix focus on top message (#3356)

This commit is contained in:
Alexander Zinchuk 2023-06-18 12:04:00 +02:00
parent 86f8ad9e2f
commit 915dbe5736
4 changed files with 26 additions and 28 deletions

View File

@ -36,7 +36,6 @@ import {
selectIsChatBotNotStarted,
selectScrollOffset,
selectThreadTopMessageId,
selectFirstMessageId,
selectChatScheduledMessages,
selectCurrentMessageIds,
selectIsCurrentUserPremium,
@ -127,7 +126,6 @@ type StateProps = {
isLoadingBotInfo?: boolean;
botInfo?: ApiBotInfo;
threadTopMessageId?: number;
threadFirstMessageId?: number;
hasLinkedChat?: boolean;
lastSyncTime?: number;
topic?: ApiTopic;
@ -170,7 +168,6 @@ const MessageList: FC<OwnProps & StateProps> = ({
firstUnreadId,
isComments,
isViewportNewest,
threadFirstMessageId,
isRestricted,
restrictionReason,
focusingId,
@ -259,23 +256,11 @@ const MessageList: FC<OwnProps & StateProps> = ({
useNativeCopySelectedMessages(copyMessagesByIds);
const messageGroups = useMemo(() => {
if (!messageIds || !messagesById) {
if (!messageIds?.length || !messagesById) {
return undefined;
}
const viewportIds = (
threadTopMessageId
&& threadFirstMessageId !== threadTopMessageId
&& (!messageIds[0] || threadFirstMessageId === messageIds[0])
)
? [threadTopMessageId, ...messageIds]
: messageIds;
if (!viewportIds.length) {
return undefined;
}
const listedMessages = viewportIds.map((id) => messagesById[id]).filter(Boolean);
const listedMessages = messageIds.map((id) => messagesById[id]).filter(Boolean);
// Service notifications have local IDs which may be not in sync with real message history
const orderRule: (keyof ApiMessage)[] = type === 'scheduled' || isServiceNotificationsChat
@ -285,7 +270,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
return listedMessages.length
? groupMessages(orderBy(listedMessages, orderRule), memoUnreadDividerBeforeIdRef.current)
: undefined;
}, [messageIds, messagesById, threadFirstMessageId, threadTopMessageId, type, isServiceNotificationsChat]);
}, [messageIds, messagesById, type, isServiceNotificationsChat]);
useInterval(() => {
if (!messageIds || !messagesById || type === 'scheduled') {
@ -746,7 +731,6 @@ export default memo(withGlobal<OwnProps>(
isComments: Boolean(threadInfo?.originChannelId),
firstUnreadId: selectFirstUnreadId(global, chatId, threadId),
isViewportNewest: type !== 'thread' || selectIsViewportNewest(global, chatId, threadId),
threadFirstMessageId: selectFirstMessageId(global, chatId, threadId),
focusingId,
isSelectModeActive: selectIsInSelectMode(global),
isLoadingBotInfo,

View File

@ -45,7 +45,7 @@ import {
selectReplyingToId,
selectTabState,
selectTheme,
selectThreadInfo,
selectThreadInfo, selectThreadTopMessageId,
} from '../../global/selectors';
import {
getCanPostInChat,
@ -140,6 +140,7 @@ type StateProps = {
shouldSendJoinRequest?: boolean;
lastSyncTime?: number;
pinnedIds?: number[];
topMessageId?: number;
};
function isImage(item: DataTransferItem) {
@ -193,6 +194,7 @@ function MiddleColumn({
shouldLoadFullChat,
lastSyncTime,
pinnedIds,
topMessageId,
}: OwnProps & StateProps) {
const {
openChat,
@ -226,7 +228,7 @@ function MiddleColumn({
getCurrentPinnedIndexes,
getLoadingPinnedId,
getForceNextPinnedInHeader,
} = usePinnedMessage(chatId, threadId, pinnedIds);
} = usePinnedMessage(chatId, threadId, pinnedIds, topMessageId);
const isMobileSearchActive = isMobile && hasCurrentTextSearch;
const closeAnimationDuration = isMobile ? LAYER_ANIMATION_DURATION_MS : undefined;
@ -720,6 +722,9 @@ export default memo(withGlobal<OwnProps>(
? selectChatMessage(global, audioChatId, audioMessageId)
: undefined;
const isCommentThread = threadId !== MAIN_THREAD_ID && !chat?.isForum;
const topMessageId = isCommentThread ? selectThreadTopMessageId(global, chatId, threadId) : undefined;
return {
...state,
chatId,
@ -737,10 +742,7 @@ export default memo(withGlobal<OwnProps>(
isPinnedMessageList,
currentUserBannedRights: chat?.currentUserBannedRights,
defaultBannedRights: chat?.defaultBannedRights,
hasPinned: (
(threadId !== MAIN_THREAD_ID && !chat?.isForum)
|| Boolean(!isPinnedMessageList && pinnedIds?.length)
),
hasPinned: isCommentThread || Boolean(!isPinnedMessageList && pinnedIds?.length),
hasAudioPlayer: Boolean(audioMessage),
hasButtonInHeader: canStartBot || canRestartBot || canSubscribe || shouldSendJoinRequest,
pinnedMessagesCount: pinnedIds ? pinnedIds.length : 0,
@ -753,6 +755,7 @@ export default memo(withGlobal<OwnProps>(
shouldSendJoinRequest,
shouldLoadFullChat,
pinnedIds,
topMessageId,
};
},
)(MiddleColumn));

View File

@ -23,7 +23,9 @@ type PinnedIntersectionChangedParams = {
export type PinnedIntersectionChangedCallback = (params: PinnedIntersectionChangedParams) => void;
export default function usePinnedMessage(chatId?: string, threadId?: number, pinnedIds?: number[]) {
export default function usePinnedMessage(
chatId?: string, threadId?: number, pinnedIds?: number[], topMessageId?: number,
) {
const [getCurrentPinnedIndexes, setCurrentPinnedIndexes] = useSignal<Record<string, number>>({});
const [getForceNextPinnedInHeader, setForceNextPinnedInHeader] = useSignal<boolean | undefined>();
const viewportPinnedIdsRef = useRef<number[] | undefined>();
@ -133,7 +135,10 @@ export default function usePinnedMessage(chatId?: string, threadId?: number, pin
if (!chatId || !threadId || !key || getLoadingPinnedId()) return false;
const global = getGlobal();
if (!pinnedIds?.length) return false;
if (!pinnedIds?.length) {
// Focusing on a post in comments
return topMessageId === messageId;
}
const index = pinnedIds.indexOf(messageId);
const newPinnedIndex = cycleRestrict(pinnedIds.length, index + 1);

View File

@ -68,7 +68,7 @@ import {
selectDraft,
selectEditingId,
selectEditingMessage,
selectEditingScheduledId,
selectEditingScheduledId, selectFirstMessageId,
selectFirstUnreadId,
selectFocusedMessageId,
selectForwardsCanBeSentToChat,
@ -1020,6 +1020,12 @@ async function loadViewportMessages<T extends GlobalState>(
const allMessages = ([] as ApiMessage[]).concat(messages, localMessages);
const byId = buildCollectionByKey(allMessages, 'id');
const ids = Object.keys(byId).map(Number);
const threadFirstMessageId = selectFirstMessageId(global, chatId, threadId) || {};
if (threadId
&& threadFirstMessageId !== threadId
&& (!ids[0] || threadFirstMessageId === ids[0])) {
ids.unshift(threadId);
}
global = addChatMessagesById(global, chatId, byId);
global = isOutlying