Message List: Various fixes for sending messages in empty chat
This commit is contained in:
parent
f4fad13266
commit
5a444dbb50
@ -4,12 +4,12 @@ import React, {
|
||||
import { getGlobal, withGlobal } from '../../lib/teact/teactn';
|
||||
|
||||
import {
|
||||
ApiAction, ApiMessage, ApiRestrictionReason, MAIN_THREAD_ID,
|
||||
ApiMessage, ApiRestrictionReason, MAIN_THREAD_ID,
|
||||
} from '../../api/types';
|
||||
import { GlobalActions, MessageListType } from '../../global/types';
|
||||
import { LoadMoreDirection } from '../../types';
|
||||
|
||||
import { ANIMATION_END_DELAY, MESSAGE_LIST_SLICE } from '../../config';
|
||||
import { ANIMATION_END_DELAY, LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SLICE } from '../../config';
|
||||
import {
|
||||
selectChatMessages,
|
||||
selectIsViewportNewest,
|
||||
@ -32,7 +32,7 @@ import { fastRaf, debounce, onTickEnd } from '../../util/schedulers';
|
||||
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
|
||||
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import { groupMessages, MessageDateGroup } from './helpers/groupMessages';
|
||||
import { groupMessages } from './helpers/groupMessages';
|
||||
import { preventMessageInputBlur } from './helpers/preventMessageInputBlur';
|
||||
import useOnChange from '../../hooks/useOnChange';
|
||||
import useStickyDates from './hooks/useStickyDates';
|
||||
@ -259,7 +259,7 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
if (isReady) {
|
||||
containerRef.current!.dataset.normalHeight = String(containerRef.current!.offsetHeight);
|
||||
}
|
||||
}, [windowHeight, isReady]);
|
||||
}, [windowHeight, isReady, canPost]);
|
||||
|
||||
// Initial message loading
|
||||
useEffect(() => {
|
||||
@ -267,6 +267,12 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
// Loading history while sending a message can return the same message and cause ambiguity
|
||||
const isFirstMessageLocal = messageIds && messageIds[0] >= LOCAL_MESSAGE_ID_BASE;
|
||||
if (isFirstMessageLocal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = containerRef.current!;
|
||||
|
||||
if (!messageIds || (
|
||||
@ -331,11 +337,13 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
}, FOCUSING_DURATION);
|
||||
}
|
||||
|
||||
const hasFirstMessageChanged = messageIds && prevMessageIds && messageIds[0] !== prevMessageIds[0];
|
||||
const hasLastMessageChanged = (
|
||||
messageIds && prevMessageIds && messageIds[messageIds.length - 1] !== prevMessageIds[prevMessageIds.length - 1]
|
||||
);
|
||||
const wasMessageAdded = hasLastMessageChanged && !hasFirstMessageChanged;
|
||||
const hasViewportShifted = (
|
||||
messageIds?.[0] !== prevMessageIds?.[0] && messageIds?.length === (MESSAGE_LIST_SLICE / 2 + 1)
|
||||
);
|
||||
const wasMessageAdded = hasLastMessageChanged && !hasViewportShifted;
|
||||
const isAlreadyFocusing = messageIds && memoFocusingIdRef.current === messageIds[messageIds.length - 1];
|
||||
|
||||
const { scrollTop, scrollHeight, offsetHeight } = container;
|
||||
@ -442,11 +450,12 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
// Used to avoid flickering when deleting a greeting that has just been sent
|
||||
&& (!listItemElementsRef.current || listItemElementsRef.current.length === 0)
|
||||
)
|
||||
|| checkSingleMessageActionByType('contactSignUp', messageGroups)
|
||||
|| (lastMessage?.content.action && lastMessage.content.action.type === 'contactSignUp')
|
||||
|| (messageIds?.length === 1 && messagesById?.[messageIds[0]]?.content.action?.type === 'contactSignUp')
|
||||
|| (lastMessage?.content?.action?.type === 'contactSignUp')
|
||||
);
|
||||
|
||||
const isGroupChatJustCreated = isGroupChat && isCreator
|
||||
&& checkSingleMessageActionByType('chatCreate', messageGroups);
|
||||
&& messageIds?.length === 1 && messagesById?.[messageIds[0]]?.content.action?.type === 'chatCreate';
|
||||
|
||||
const className = buildClassName(
|
||||
'MessageList custom-scroll',
|
||||
@ -512,16 +521,6 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
function checkSingleMessageActionByType(type: ApiAction['type'], messageGroups?: MessageDateGroup[]) {
|
||||
return messageGroups
|
||||
&& messageGroups.length === 1
|
||||
&& messageGroups[0].senderGroups.length === 1
|
||||
&& messageGroups[0].senderGroups[0].length === 1
|
||||
&& 'content' in messageGroups[0].senderGroups[0][0]
|
||||
&& messageGroups[0].senderGroups[0][0].content.action
|
||||
&& messageGroups[0].senderGroups[0][0].content.action.type === type;
|
||||
}
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global, { chatId, threadId, type }): StateProps => {
|
||||
const chat = selectChat(global, chatId);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { RefObject } from 'react';
|
||||
import { getDispatch } from '../../../lib/teact/teactn';
|
||||
import { useCallback, useMemo, useRef } from '../../../lib/teact/teact';
|
||||
import { useMemo, useRef } from '../../../lib/teact/teact';
|
||||
|
||||
import { LoadMoreDirection } from '../../../types';
|
||||
import { MessageListType } from '../../../global/types';
|
||||
|
||||
import { debounce } from '../../../util/schedulers';
|
||||
import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver';
|
||||
import { MESSAGE_LIST_SENSITIVE_AREA } from '../../../config';
|
||||
import { LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SENSITIVE_AREA } from '../../../config';
|
||||
import resetScroll from '../../../util/resetScroll';
|
||||
import useOnChange from '../../../hooks/useOnChange';
|
||||
|
||||
@ -42,7 +42,7 @@ export default function useScrollHooks(
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const fabTriggerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const toggleScrollTools = useCallback(() => {
|
||||
function toggleScrollTools() {
|
||||
if (!isActive) return;
|
||||
|
||||
if (!messageIds || !messageIds.length) {
|
||||
@ -64,7 +64,7 @@ export default function useScrollHooks(
|
||||
|
||||
onFabToggle(isUnread ? !isAtBottom : !isNearBottom);
|
||||
onNotchToggle(!isAtBottom);
|
||||
}, [isActive, messageIds, isViewportNewest, containerRef, onFabToggle, isUnread, onNotchToggle]);
|
||||
}
|
||||
|
||||
const {
|
||||
observe: observeIntersection,
|
||||
@ -76,6 +76,12 @@ export default function useScrollHooks(
|
||||
return;
|
||||
}
|
||||
|
||||
// Loading history while sending a message can return the same message and cause ambiguity
|
||||
const isFirstMessageLocal = messageIds[0] >= LOCAL_MESSAGE_ID_BASE;
|
||||
if (isFirstMessageLocal) {
|
||||
return;
|
||||
}
|
||||
|
||||
const triggerEntry = entries.find(({ isIntersecting }) => isIntersecting);
|
||||
if (!triggerEntry) {
|
||||
return;
|
||||
|
||||
@ -671,6 +671,7 @@ async function loadViewportMessages(
|
||||
global = isOutlying
|
||||
? updateOutlyingIds(global, chatId, threadId, ids)
|
||||
: updateListedIds(global, chatId, threadId, ids);
|
||||
|
||||
global = addUsers(global, buildCollectionByKey(users, 'id'));
|
||||
global = addChats(global, buildCollectionByKey(chats, 'id'));
|
||||
global = updateThreadInfos(global, chatId, threadInfos);
|
||||
@ -679,7 +680,7 @@ async function loadViewportMessages(
|
||||
const outlyingIds = selectOutlyingIds(global, chatId, threadId);
|
||||
|
||||
if (isOutlying && listedIds && outlyingIds) {
|
||||
if (areSortedArraysIntersecting(listedIds, outlyingIds)) {
|
||||
if (!outlyingIds.length || areSortedArraysIntersecting(listedIds, outlyingIds)) {
|
||||
global = updateListedIds(global, chatId, threadId, outlyingIds);
|
||||
listedIds = selectListedIds(global, chatId, threadId);
|
||||
global = replaceThreadParam(global, chatId, threadId, 'outlyingIds', undefined);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user