Message List: Various fixes for local message IDs
This commit is contained in:
parent
2647c561a9
commit
ea0da789ce
@ -35,7 +35,6 @@ import type {
|
||||
|
||||
import {
|
||||
DELETED_COMMENTS_CHANNEL_ID,
|
||||
LOCAL_MESSAGE_ID_BASE,
|
||||
SERVICE_NOTIFICATIONS_USER_ID,
|
||||
SPONSORED_MESSAGE_CACHE_MS,
|
||||
SUPPORTED_AUDIO_CONTENT_TYPES,
|
||||
@ -56,7 +55,9 @@ import { buildApiCallDiscardReason } from './calls';
|
||||
const LOCAL_MEDIA_UPLOADING_TEMP_ID = 'temp';
|
||||
const INPUT_WAVEFORM_LENGTH = 63;
|
||||
|
||||
let localMessageCounter = LOCAL_MESSAGE_ID_BASE;
|
||||
let localMessageCounter = 0;
|
||||
const getNextLocalMessageId = () => parseFloat(`${Date.now()}.${localMessageCounter++}`);
|
||||
|
||||
let currentUserId!: string;
|
||||
|
||||
export function setMessageBuilderCurrentUserId(_currentUserId: string) {
|
||||
@ -120,7 +121,7 @@ export function buildApiMessageFromNotification(
|
||||
notification: GramJs.UpdateServiceNotification,
|
||||
currentDate: number,
|
||||
): ApiMessage {
|
||||
const localId = localMessageCounter++;
|
||||
const localId = getNextLocalMessageId();
|
||||
const content = buildMessageContent(notification);
|
||||
|
||||
return {
|
||||
@ -1148,7 +1149,7 @@ export function buildLocalMessage(
|
||||
sendAs?: ApiChat | ApiUser,
|
||||
serverTimeOffset = 0,
|
||||
): ApiMessage {
|
||||
const localId = localMessageCounter++;
|
||||
const localId = getNextLocalMessageId();
|
||||
const media = attachment && buildUploadingMedia(attachment);
|
||||
const isChannel = chat.type === 'chatTypeChannel';
|
||||
|
||||
@ -1186,7 +1187,7 @@ export function buildLocalForwardedMessage(
|
||||
serverTimeOffset: number,
|
||||
scheduledAt?: number,
|
||||
): ApiMessage {
|
||||
const localId = localMessageCounter++;
|
||||
const localId = getNextLocalMessageId();
|
||||
const {
|
||||
content,
|
||||
chatId: fromChatId,
|
||||
|
||||
@ -9,7 +9,7 @@ import { MAIN_THREAD_ID } from '../../api/types';
|
||||
import type { MessageListType } from '../../global/types';
|
||||
import { LoadMoreDirection } from '../../types';
|
||||
|
||||
import { ANIMATION_END_DELAY, LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SLICE } from '../../config';
|
||||
import { ANIMATION_END_DELAY, LOCAL_MESSAGE_MIN_ID, MESSAGE_LIST_SLICE } from '../../config';
|
||||
import {
|
||||
selectChatMessages,
|
||||
selectIsViewportNewest,
|
||||
@ -303,7 +303,7 @@ const MessageList: FC<OwnProps & StateProps> = ({
|
||||
}
|
||||
|
||||
// Loading history while sending a message can return the same message and cause ambiguity
|
||||
const isLastMessageLocal = messageIds && messageIds[messageIds.length - 1] >= LOCAL_MESSAGE_ID_BASE;
|
||||
const isLastMessageLocal = messageIds && messageIds[messageIds.length - 1] > LOCAL_MESSAGE_MIN_ID;
|
||||
if (isLastMessageLocal) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import buildClassName from '../../util/buildClassName';
|
||||
import { compact } from '../../util/iteratees';
|
||||
import { formatHumanDate } from '../../util/dateFormat';
|
||||
import {
|
||||
getMessageHtmlId, getMessageOriginalId, isActionMessage, isOwnMessage,
|
||||
getMessageHtmlId, getMessageOriginalId, isActionMessage, isOwnMessage, isServiceNotificationMessage,
|
||||
} from '../../global/helpers';
|
||||
import useLang from '../../hooks/useLang';
|
||||
import type { MessageDateGroup } from './helpers/groupMessages';
|
||||
@ -182,10 +182,8 @@ const MessageListContent: FC<OwnProps> = ({
|
||||
currentDocumentGroupId = documentGroupId;
|
||||
|
||||
const originalId = getMessageOriginalId(message);
|
||||
// Scheduled messages can have local IDs in the middle of the list,
|
||||
// and keys should be ordered, so we prefix it with a date.
|
||||
// However, this may lead to issues if server date is not synchronized with the local one.
|
||||
const key = type !== 'scheduled' ? originalId : `${message.date}_${originalId}`;
|
||||
// Service notifications saved in cache in previous versions may share the same `previousLocalId`
|
||||
const key = isServiceNotificationMessage(message) ? `${message.date}_${originalId}` : originalId;
|
||||
|
||||
return compact([
|
||||
message.id === memoUnreadDividerBeforeIdRef.current && unreadDivider,
|
||||
|
||||
@ -5,7 +5,7 @@ import { useMemo, useRef } from '../../../lib/teact/teact';
|
||||
import { LoadMoreDirection } from '../../../types';
|
||||
import type { MessageListType } from '../../../global/types';
|
||||
|
||||
import { LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SLICE } from '../../../config';
|
||||
import { LOCAL_MESSAGE_MIN_ID, MESSAGE_LIST_SLICE } from '../../../config';
|
||||
import { IS_SCROLL_PATCH_NEEDED, MESSAGE_LIST_SENSITIVE_AREA } from '../../../util/environment';
|
||||
import { debounce } from '../../../util/schedulers';
|
||||
import { useIntersectionObserver, useOnIntersect } from '../../../hooks/useIntersectionObserver';
|
||||
@ -84,7 +84,7 @@ export default function useScrollHooks(
|
||||
}
|
||||
|
||||
// Loading history while sending a message can return the same message and cause ambiguity
|
||||
const isFirstMessageLocal = messageIds[0] >= LOCAL_MESSAGE_ID_BASE;
|
||||
const isFirstMessageLocal = messageIds[0] > LOCAL_MESSAGE_MIN_ID;
|
||||
if (isFirstMessageLocal) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import type { IAlbum, ISettings } from '../../../types';
|
||||
import type { IAlbumLayout } from './helpers/calculateAlbumLayout';
|
||||
import { AlbumRectPart } from './helpers/calculateAlbumLayout';
|
||||
|
||||
import { getMessageContent, getMessageHtmlId } from '../../../global/helpers';
|
||||
import { getMessageContent, getMessageHtmlId, getMessageOriginalId } from '../../../global/helpers';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../global';
|
||||
import withSelectControl from './hocs/withSelectControl';
|
||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
@ -66,7 +66,7 @@ const Album: FC<OwnProps & StateProps> = ({
|
||||
|
||||
function renderAlbumMessage(message: ApiMessage, index: number) {
|
||||
const { photo, video } = getMessageContent(message);
|
||||
const fileUpload = uploadsById[message.previousLocalId || message.id];
|
||||
const fileUpload = uploadsById[getMessageOriginalId(message)];
|
||||
const uploadProgress = fileUpload?.progress;
|
||||
const { dimensions, sides } = albumLayout.layout[index];
|
||||
|
||||
|
||||
@ -107,7 +107,7 @@ export const MOBILE_SCREEN_MAX_WIDTH = 600; // px
|
||||
export const MOBILE_SCREEN_LANDSCAPE_MAX_WIDTH = 950; // px
|
||||
export const MOBILE_SCREEN_LANDSCAPE_MAX_HEIGHT = 450; // px
|
||||
|
||||
export const LOCAL_MESSAGE_ID_BASE = 1e9;
|
||||
export const LOCAL_MESSAGE_MIN_ID = 1e11; // `Date.now()` is always used as base
|
||||
export const TMP_CHAT_ID = '0';
|
||||
|
||||
export const ANIMATION_END_DELAY = 100;
|
||||
|
||||
@ -68,7 +68,7 @@ import {
|
||||
selectSponsoredMessage,
|
||||
} from '../../selectors';
|
||||
import { debounce, onTickEnd, rafPromise } from '../../../util/schedulers';
|
||||
import { isServiceNotificationMessage } from '../../helpers';
|
||||
import { getMessageOriginalId, isServiceNotificationMessage } from '../../helpers';
|
||||
import { getTranslation } from '../../../util/langProvider';
|
||||
|
||||
const uploadProgressCallbacks = new Map<number, ApiOnProgress>();
|
||||
@ -302,7 +302,7 @@ addActionHandler('editMessage', (global, actions, payload) => {
|
||||
addActionHandler('cancelSendingMessage', (global, actions, payload) => {
|
||||
const { chatId, messageId } = payload!;
|
||||
const message = selectChatMessage(global, chatId, messageId);
|
||||
const progressCallback = message && uploadProgressCallbacks.get(message.previousLocalId || message.id);
|
||||
const progressCallback = message && uploadProgressCallbacks.get(getMessageOriginalId(message));
|
||||
if (progressCallback) {
|
||||
cancelApiProgress(progressCallback);
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ import {
|
||||
selectLocalAnimatedEmoji,
|
||||
} from '../../selectors';
|
||||
import {
|
||||
getMessageContent, isUserId, isMessageLocal, getMessageText, checkIfHasUnreadReactions,
|
||||
getMessageContent, isUserId, isMessageLocal, getMessageText, checkIfHasUnreadReactions, getMessageOriginalId,
|
||||
} from '../../helpers';
|
||||
import { onTickEnd } from '../../../util/schedulers';
|
||||
import { updateUnreadReactions } from '../../reducers/reactions';
|
||||
@ -665,7 +665,7 @@ function updateChatLastMessage(
|
||||
|
||||
if (currentLastMessage && !force) {
|
||||
const isSameOrNewer = (
|
||||
currentLastMessage.id === message.id || currentLastMessage.id === message.previousLocalId
|
||||
currentLastMessage.id === getMessageOriginalId(message)
|
||||
) || message.id > currentLastMessage.id;
|
||||
|
||||
if (!isSameOrNewer) {
|
||||
|
||||
@ -6,7 +6,7 @@ import type { LangFn } from '../../hooks/useLang';
|
||||
|
||||
import {
|
||||
CONTENT_NOT_SUPPORTED,
|
||||
LOCAL_MESSAGE_ID_BASE,
|
||||
LOCAL_MESSAGE_MIN_ID,
|
||||
RE_LINK_TEMPLATE,
|
||||
SERVICE_NOTIFICATIONS_USER_ID,
|
||||
} from '../../config';
|
||||
@ -175,7 +175,7 @@ export function getSendingState(message: ApiMessage) {
|
||||
}
|
||||
|
||||
export function isMessageLocal(message: ApiMessage) {
|
||||
return message.id >= LOCAL_MESSAGE_ID_BASE;
|
||||
return message.id > LOCAL_MESSAGE_MIN_ID;
|
||||
}
|
||||
|
||||
export function isHistoryClearMessage(message: ApiMessage) {
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
MAIN_THREAD_ID,
|
||||
} from '../../api/types';
|
||||
|
||||
import { LOCAL_MESSAGE_ID_BASE, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
|
||||
import { LOCAL_MESSAGE_MIN_ID, REPLIES_USER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
|
||||
import {
|
||||
selectChat, selectChatBot, selectIsChatWithBot, selectIsChatWithSelf,
|
||||
} from './chats';
|
||||
@ -37,6 +37,7 @@ import {
|
||||
getMessageVoice,
|
||||
getMessageDocument,
|
||||
getMessageWebPagePhoto,
|
||||
getMessageOriginalId,
|
||||
} from '../helpers';
|
||||
import { findLast } from '../../util/iteratees';
|
||||
import { selectIsStickerFavorite } from './symbols';
|
||||
@ -253,7 +254,7 @@ export function selectIsViewportNewest(global: GlobalState, chatId: string, thre
|
||||
}
|
||||
|
||||
// Edge case: outgoing `lastMessage` is updated with a delay to optimize animation
|
||||
if (lastMessageId >= LOCAL_MESSAGE_ID_BASE && !selectChatMessage(global, chatId, lastMessageId)) {
|
||||
if (lastMessageId > LOCAL_MESSAGE_MIN_ID && !selectChatMessage(global, chatId, lastMessageId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -310,7 +311,7 @@ export function selectFocusedMessageId(global: GlobalState, chatId: string) {
|
||||
export function selectIsMessageFocused(global: GlobalState, message: ApiMessage) {
|
||||
const focusedId = selectFocusedMessageId(global, message.chatId);
|
||||
|
||||
return focusedId ? focusedId === message.id || focusedId === message.previousLocalId : false;
|
||||
return focusedId ? focusedId === getMessageOriginalId(message) : false;
|
||||
}
|
||||
|
||||
export function selectIsMessageUnread(global: GlobalState, message: ApiMessage) {
|
||||
@ -554,7 +555,7 @@ export function selectActiveDownloadIds(global: GlobalState, chatId: string) {
|
||||
}
|
||||
|
||||
export function selectUploadProgress(global: GlobalState, message: ApiMessage) {
|
||||
return global.fileUploads.byMessageLocalId[message.previousLocalId || message.id]?.progress;
|
||||
return global.fileUploads.byMessageLocalId[getMessageOriginalId(message)]?.progress;
|
||||
}
|
||||
|
||||
export function selectRealLastReadId(global: GlobalState, chatId: string, threadId: number) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user