Middle Header: Fix pinned message getting stuck (#2519)

This commit is contained in:
Alexander Zinchuk 2023-02-08 00:47:39 +01:00
parent 0be5085d69
commit f0574f78a5
5 changed files with 60 additions and 5 deletions

View File

@ -92,6 +92,7 @@ type StateProps = {
isChatWithSelf?: boolean;
lastSyncTime?: number;
hasButtonInHeader?: boolean;
hasReachedFocusedMessage?: boolean;
shouldSkipHistoryAnimations?: boolean;
currentTransitionKey: number;
connectionState?: GlobalState['connectionState'];
@ -121,6 +122,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
shouldSkipHistoryAnimations,
currentTransitionKey,
connectionState,
hasReachedFocusedMessage,
isSyncing,
}) => {
const {
@ -129,6 +131,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
focusMessage,
openChat,
openPreviousChat,
setReachedFocusedMessage,
loadPinnedMessages,
toggleLeftColumn,
exitMessageSelectMode,
@ -136,6 +139,7 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
const lang = useLang();
const isBackButtonActive = useRef(true);
const [isWaitingForPinnedMessageFocus, setWaitingForPinnedMessageFocus] = useState(false);
const { isTablet } = useAppLayout();
const [pinnedMessageIndex, setPinnedMessageIndex] = useState(0);
@ -157,8 +161,22 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
// Reset pinned index when switching chats and pinning/unpinning
useEffect(() => {
setPinnedMessageIndex(0);
setWaitingForPinnedMessageFocus(false);
}, [pinnedMessageIds]);
useEffect(() => {
if (hasReachedFocusedMessage && isWaitingForPinnedMessageFocus) {
setReachedFocusedMessage({ hasReached: false });
setWaitingForPinnedMessageFocus(false);
const newIndex = cycleRestrict(pinnedMessagesCount || 1, pinnedMessageIndex + 1);
setPinnedMessageIndex(newIndex);
}
}, [
hasReachedFocusedMessage, isWaitingForPinnedMessageFocus, pinnedMessageIndex, pinnedMessagesCount,
setReachedFocusedMessage,
]);
useEnsureMessage(chatId, pinnedMessageId, pinnedMessage);
const { width: windowWidth } = useWindowSize();
@ -184,10 +202,9 @@ const MiddleHeader: FC<OwnProps & StateProps> = ({
chatId: pinnedMessage.chatId, threadId, messageId: pinnedMessage.id, noForumTopicPanel: true,
});
const newIndex = cycleRestrict(pinnedMessagesCount || 1, pinnedMessageIndex + 1);
setPinnedMessageIndex(newIndex);
setWaitingForPinnedMessageFocus(true);
}
}, [pinnedMessage, focusMessage, threadId, pinnedMessagesCount, pinnedMessageIndex]);
}, [pinnedMessage, focusMessage, threadId]);
const handleAllPinnedClick = useCallback(() => {
openChat({ id: chatId, threadId, type: 'pinned' });
@ -492,6 +509,7 @@ export default memo(withGlobal<OwnProps>(
);
const shouldSendJoinRequest = Boolean(chat?.isNotJoined && chat.isJoinRequest);
const typingStatus = selectThreadParam(global, chatId, threadId, 'typingStatus');
const focusedMessage = selectTabState(global).focusedMessage;
const state: StateProps = {
typingStatus,
@ -508,6 +526,7 @@ export default memo(withGlobal<OwnProps>(
connectionState: global.connectionState,
isSyncing: global.isSyncing,
hasButtonInHeader: canStartBot || canRestartBot || canSubscribe || shouldSendJoinRequest,
hasReachedFocusedMessage: !focusedMessage || focusedMessage.hasReachedMessage,
};
const messagesById = selectChatMessages(global, chatId);

View File

@ -1,3 +1,5 @@
import { getActions } from '../../../../global';
import type { FocusDirection } from '../../../../types';
import { useLayoutEffect } from '../../../../lib/teact/teact';
@ -15,10 +17,16 @@ export default function useFocusMessage(
noFocusHighlight?: boolean,
isResizingContainer?: boolean,
) {
const { setReachedFocusedMessage } = getActions();
useLayoutEffect(() => {
if (isFocused && elementRef.current) {
const messagesContainer = elementRef.current.closest<HTMLDivElement>('.MessageList')!;
setReachedFocusedMessage({
hasReached: true,
});
fastSmoothScroll(
messagesContainer,
elementRef.current,
@ -31,5 +39,7 @@ export default function useFocusMessage(
isResizingContainer,
);
}
}, [elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer]);
}, [
elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, setReachedFocusedMessage,
]);
}

View File

@ -22,7 +22,7 @@ import {
replaceThreadParam,
replaceTabThreadParam,
updateFocusDirection,
updateFocusedMessage,
updateFocusedMessage, updateFocusedMessageReached,
} from '../../reducers';
import {
selectCurrentChat,
@ -368,6 +368,12 @@ addActionHandler('focusNextReply', (global, actions, payload): ActionReturnType
return undefined;
});
addActionHandler('setReachedFocusedMessage', (global, actions, payload): ActionReturnType => {
const { hasReached = false, tabId = getCurrentTabId() } = payload;
return updateFocusedMessageReached(global, hasReached, tabId);
});
addActionHandler('focusMessage', (global, actions, payload): ActionReturnType => {
const {
chatId, threadId = MAIN_THREAD_ID, messageListType = 'thread', noHighlight, groupedId, groupedChatId,

View File

@ -512,6 +512,22 @@ export function updateFocusedMessage<T extends GlobalState>(
}, tabId);
}
export function updateFocusedMessageReached<T extends GlobalState>(
global: T, hasReachedMessage: boolean,
...[tabId = getCurrentTabId()]: TabArgs<T>
): T {
const focusedMessage = selectTabState(global, tabId).focusedMessage;
if (!focusedMessage) return global;
return updateTabState(global, {
focusedMessage: {
...focusedMessage,
hasReachedMessage,
},
}, tabId);
}
export function updateSponsoredMessage<T extends GlobalState>(
global: T, chatId: string, message: ApiSponsoredMessage,
): T {

View File

@ -214,6 +214,7 @@ export type TabState = {
direction?: FocusDirection;
noHighlight?: boolean;
isResizingContainer?: boolean;
hasReachedMessage?: boolean;
};
selectedMessages?: {
@ -1445,6 +1446,9 @@ export interface ActionPayloads {
showDialog: {
data: TabState['dialogs'][number];
} & WithTabId;
setReachedFocusedMessage: {
hasReached?: boolean;
} & WithTabId;
focusMessage: {
chatId: string;
threadId?: number;