[Perf] Simplify usage of serverTimeOffset

This commit is contained in:
Alexander Zinchuk 2023-01-22 18:12:27 +01:00
parent 2d23ec775e
commit 9080082823
39 changed files with 115 additions and 218 deletions

View File

@ -20,7 +20,7 @@ import {
buildApiPeerId, getApiChatIdFromMtpPeer, isPeerChat, isPeerUser, buildApiPeerId, getApiChatIdFromMtpPeer, isPeerChat, isPeerUser,
} from './peers'; } from './peers';
import { omitVirtualClassFields } from './helpers'; import { omitVirtualClassFields } from './helpers';
import { getServerTime } from '../../../util/serverTime'; import { getServerTime, getServerTimeOffset } from '../../../util/serverTime';
import { buildApiReaction } from './messages'; import { buildApiReaction } from './messages';
import { buildApiUsernames } from './common'; import { buildApiUsernames } from './common';
@ -79,14 +79,13 @@ function buildApiChatFieldsFromPeerEntity(
export function buildApiChatFromDialog( export function buildApiChatFromDialog(
dialog: GramJs.Dialog, dialog: GramJs.Dialog,
peerEntity: GramJs.TypeUser | GramJs.TypeChat, peerEntity: GramJs.TypeUser | GramJs.TypeChat,
serverTimeOffset: number,
): ApiChat { ): ApiChat {
const { const {
peer, folderId, unreadMark, unreadCount, unreadMentionsCount, unreadReactionsCount, peer, folderId, unreadMark, unreadCount, unreadMentionsCount, unreadReactionsCount,
notifySettings: { silent, muteUntil }, notifySettings: { silent, muteUntil },
readOutboxMaxId, readInboxMaxId, draft, readOutboxMaxId, readInboxMaxId, draft,
} = dialog; } = dialog;
const isMuted = silent || (typeof muteUntil === 'number' && getServerTime(serverTimeOffset) < muteUntil); const isMuted = silent || (typeof muteUntil === 'number' && getServerTime() < muteUntil);
return { return {
id: getApiChatIdFromMtpPeer(peer), id: getApiChatIdFromMtpPeer(peer),
@ -316,7 +315,6 @@ export function buildChatMembers(
export function buildChatTypingStatus( export function buildChatTypingStatus(
update: GramJs.UpdateUserTyping | GramJs.UpdateChatUserTyping | GramJs.UpdateChannelUserTyping, update: GramJs.UpdateUserTyping | GramJs.UpdateChatUserTyping | GramJs.UpdateChannelUserTyping,
serverTimeOffset: number,
) { ) {
let action: string = ''; let action: string = '';
let emoticon: string | undefined; let emoticon: string | undefined;
@ -361,7 +359,7 @@ export function buildChatTypingStatus(
action, action,
...(emoticon && { emoji: emoticon }), ...(emoticon && { emoji: emoticon }),
...(!(update instanceof GramJs.UpdateUserTyping) && { userId: getApiChatIdFromMtpPeer(update.fromId) }), ...(!(update instanceof GramJs.UpdateUserTyping) && { userId: getApiChatIdFromMtpPeer(update.fromId) }),
timestamp: Date.now() + serverTimeOffset * 1000, timestamp: Date.now() + getServerTimeOffset() * 1000,
}; };
} }

View File

@ -60,6 +60,7 @@ import { addPhotoToLocalDb, resolveMessageApiChatId, serializeBytes } from '../h
import { buildApiPeerId, getApiChatIdFromMtpPeer, isPeerUser } from './peers'; import { buildApiPeerId, getApiChatIdFromMtpPeer, isPeerUser } from './peers';
import { buildApiCallDiscardReason } from './calls'; import { buildApiCallDiscardReason } from './calls';
import { getEmojiOnlyCountForMessage } from '../../../global/helpers/getEmojiOnlyCountForMessage'; import { getEmojiOnlyCountForMessage } from '../../../global/helpers/getEmojiOnlyCountForMessage';
import { getServerTimeOffset } from '../../../util/serverTime';
const LOCAL_MEDIA_UPLOADING_TEMP_ID = 'temp'; const LOCAL_MEDIA_UPLOADING_TEMP_ID = 'temp';
const INPUT_WAVEFORM_LENGTH = 63; const INPUT_WAVEFORM_LENGTH = 63;
@ -1263,7 +1264,6 @@ export function buildLocalMessage(
groupedId?: string, groupedId?: string,
scheduledAt?: number, scheduledAt?: number,
sendAs?: ApiChat | ApiUser, sendAs?: ApiChat | ApiUser,
serverTimeOffset = 0,
): ApiMessage { ): ApiMessage {
const localId = getNextLocalMessageId(); const localId = getNextLocalMessageId();
const media = attachment && buildUploadingMedia(attachment); const media = attachment && buildUploadingMedia(attachment);
@ -1286,7 +1286,7 @@ export function buildLocalMessage(
...(poll && buildNewPoll(poll, localId)), ...(poll && buildNewPoll(poll, localId)),
...(contact && { contact }), ...(contact && { contact }),
}, },
date: scheduledAt || Math.round(Date.now() / 1000) + serverTimeOffset, date: scheduledAt || Math.round(Date.now() / 1000) + getServerTimeOffset(),
isOutgoing: !isChannel, isOutgoing: !isChannel,
senderId: sendAs?.id || currentUserId, senderId: sendAs?.id || currentUserId,
...(replyingTo && { replyToMessageId: replyingTo }), ...(replyingTo && { replyToMessageId: replyingTo }),
@ -1312,7 +1312,6 @@ export function buildLocalForwardedMessage({
toChat, toChat,
toThreadId, toThreadId,
message, message,
serverTimeOffset,
scheduledAt, scheduledAt,
noAuthors, noAuthors,
noCaptions, noCaptions,
@ -1321,7 +1320,6 @@ export function buildLocalForwardedMessage({
toChat: ApiChat; toChat: ApiChat;
toThreadId?: number; toThreadId?: number;
message: ApiMessage; message: ApiMessage;
serverTimeOffset: number;
scheduledAt?: number; scheduledAt?: number;
noAuthors?: boolean; noAuthors?: boolean;
noCaptions?: boolean; noCaptions?: boolean;
@ -1358,7 +1356,7 @@ export function buildLocalForwardedMessage({
id: localId, id: localId,
chatId: toChat.id, chatId: toChat.id,
content: updatedContent, content: updatedContent,
date: scheduledAt || Math.round(Date.now() / 1000) + serverTimeOffset, date: scheduledAt || Math.round(Date.now() / 1000) + getServerTimeOffset(),
isOutgoing: !asIncomingInChatWithSelf && toChat.type !== 'chatTypeChannel', isOutgoing: !asIncomingInChatWithSelf && toChat.type !== 'chatTypeChannel',
senderId: currentUserId, senderId: currentUserId,
sendingState: 'messageSendingStatePending', sendingState: 'messageSendingStatePending',

View File

@ -123,7 +123,7 @@ export function buildPrivacyRules(rules: GramJs.TypePrivacyRule[]): ApiPrivacySe
} }
export function buildApiNotifyException( export function buildApiNotifyException(
notifySettings: GramJs.TypePeerNotifySettings, peer: GramJs.TypePeer, serverTimeOffset: number, notifySettings: GramJs.TypePeerNotifySettings, peer: GramJs.TypePeer,
) { ) {
const { const {
silent, muteUntil, showPreviews, otherSound, silent, muteUntil, showPreviews, otherSound,
@ -133,14 +133,14 @@ export function buildApiNotifyException(
return { return {
chatId: getApiChatIdFromMtpPeer(peer), chatId: getApiChatIdFromMtpPeer(peer),
isMuted: silent || (typeof muteUntil === 'number' && getServerTime(serverTimeOffset) < muteUntil), isMuted: silent || (typeof muteUntil === 'number' && getServerTime() < muteUntil),
...(!hasSound && { isSilent: true }), ...(!hasSound && { isSilent: true }),
...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }), ...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }),
}; };
} }
export function buildApiNotifyExceptionTopic( export function buildApiNotifyExceptionTopic(
notifySettings: GramJs.TypePeerNotifySettings, peer: GramJs.TypePeer, topicId: number, serverTimeOffset: number, notifySettings: GramJs.TypePeerNotifySettings, peer: GramJs.TypePeer, topicId: number,
) { ) {
const { const {
silent, muteUntil, showPreviews, otherSound, silent, muteUntil, showPreviews, otherSound,
@ -151,7 +151,7 @@ export function buildApiNotifyExceptionTopic(
return { return {
chatId: getApiChatIdFromMtpPeer(peer), chatId: getApiChatIdFromMtpPeer(peer),
topicId, topicId,
isMuted: silent || (typeof muteUntil === 'number' && getServerTime(serverTimeOffset) < muteUntil), isMuted: silent || (typeof muteUntil === 'number' && getServerTime() < muteUntil),
...(!hasSound && { isSilent: true }), ...(!hasSound && { isSilent: true }),
...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }), ...(showPreviews !== undefined && { shouldShowPreviews: Boolean(showPreviews) }),
}; };

View File

@ -81,14 +81,12 @@ export async function fetchChats({
offsetDate, offsetDate,
archived, archived,
withPinned, withPinned,
serverTimeOffset,
lastLocalServiceMessage, lastLocalServiceMessage,
}: { }: {
limit: number; limit: number;
offsetDate?: number; offsetDate?: number;
archived?: boolean; archived?: boolean;
withPinned?: boolean; withPinned?: boolean;
serverTimeOffset: number;
lastLocalServiceMessage?: ApiMessage; lastLocalServiceMessage?: ApiMessage;
}) { }) {
const result = await invokeRequest(new GramJs.messages.GetDialogs({ const result = await invokeRequest(new GramJs.messages.GetDialogs({
@ -144,7 +142,7 @@ export async function fetchChats({
} }
const peerEntity = peersByKey[getPeerKey(dialog.peer)]; const peerEntity = peersByKey[getPeerKey(dialog.peer)];
const chat = buildApiChatFromDialog(dialog, peerEntity, serverTimeOffset); const chat = buildApiChatFromDialog(dialog, peerEntity);
if ( if (
chat.id === SERVICE_NOTIFICATIONS_USER_ID chat.id === SERVICE_NOTIFICATIONS_USER_ID
@ -294,11 +292,10 @@ export async function fetchChat({
export async function requestChatUpdate({ export async function requestChatUpdate({
chat, chat,
serverTimeOffset,
lastLocalMessage, lastLocalMessage,
noLastMessage, noLastMessage,
}: { }: {
chat: ApiChat; serverTimeOffset: number; lastLocalMessage?: ApiMessage; noLastMessage?: boolean; chat: ApiChat; lastLocalMessage?: ApiMessage; noLastMessage?: boolean;
}) { }) {
const { id, accessHash } = chat; const { id, accessHash } = chat;
@ -334,7 +331,7 @@ export async function requestChatUpdate({
'@type': 'updateChat', '@type': 'updateChat',
id, id,
chat: { chat: {
...buildApiChatFromDialog(dialog, peerEntity, serverTimeOffset), ...buildApiChatFromDialog(dialog, peerEntity),
...(!noLastMessage && { lastMessage }), ...(!noLastMessage && { lastMessage }),
}, },
}); });
@ -558,9 +555,9 @@ async function getFullChannelInfo(
} }
export async function updateChatMutedState({ export async function updateChatMutedState({
chat, isMuted, serverTimeOffset, chat, isMuted,
}: { }: {
chat: ApiChat; isMuted: boolean; serverTimeOffset: number; chat: ApiChat; isMuted: boolean;
}) { }) {
await invokeRequest(new GramJs.account.UpdateNotifySettings({ await invokeRequest(new GramJs.account.UpdateNotifySettings({
peer: new GramJs.InputNotifyPeer({ peer: new GramJs.InputNotifyPeer({
@ -577,7 +574,6 @@ export async function updateChatMutedState({
void requestChatUpdate({ void requestChatUpdate({
chat, chat,
serverTimeOffset,
noLastMessage: true, noLastMessage: true,
}); });
} }
@ -585,8 +581,7 @@ export async function updateChatMutedState({
export async function updateTopicMutedState({ export async function updateTopicMutedState({
chat, topicId, isMuted, chat, topicId, isMuted,
}: { }: {
chat: ApiChat; topicId: number; isMuted: boolean; serverTimeOffset: number; chat: ApiChat; topicId: number; isMuted: boolean;
}) { }) {
await invokeRequest(new GramJs.account.UpdateNotifySettings({ await invokeRequest(new GramJs.account.UpdateNotifySettings({
peer: new GramJs.InputNotifyForumTopic({ peer: new GramJs.InputNotifyForumTopic({

View File

@ -175,11 +175,6 @@ function handleGramJsUpdate(update: any) {
isConnected = update.state === connection.UpdateConnectionState.connected; isConnected = update.state === connection.UpdateConnectionState.connected;
} else if (update instanceof GramJs.UpdatesTooLong) { } else if (update instanceof GramJs.UpdatesTooLong) {
void handleTerminatedSession(); void handleTerminatedSession();
} else if (update instanceof connection.UpdateServerTimeOffset) {
onUpdate({
'@type': 'updateServerTimeOffset',
serverTimeOffset: update.timeOffset,
});
} else if (update instanceof GramJs.UpdateConfig) { } else if (update instanceof GramJs.UpdateConfig) {
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
const currentUser = (update as GramJs.UpdateConfig & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] }) const currentUser = (update as GramJs.UpdateConfig & { _entities?: (GramJs.TypeUser | GramJs.TypeChat)[] })

View File

@ -64,6 +64,7 @@ import {
import { interpolateArray } from '../../../util/waveform'; import { interpolateArray } from '../../../util/waveform';
import { requestChatUpdate } from './chats'; import { requestChatUpdate } from './chats';
import { getEmojiOnlyCountForMessage } from '../../../global/helpers/getEmojiOnlyCountForMessage'; import { getEmojiOnlyCountForMessage } from '../../../global/helpers/getEmojiOnlyCountForMessage';
import { getServerTimeOffset } from '../../../util/serverTime';
const FAST_SEND_TIMEOUT = 1000; const FAST_SEND_TIMEOUT = 1000;
const INPUT_WAVEFORM_LENGTH = 63; const INPUT_WAVEFORM_LENGTH = 63;
@ -216,7 +217,6 @@ export function sendMessage(
groupedId, groupedId,
noWebPage, noWebPage,
sendAs, sendAs,
serverTimeOffset,
shouldUpdateStickerSetsOrder, shouldUpdateStickerSetsOrder,
}: { }: {
chat: ApiChat; chat: ApiChat;
@ -234,7 +234,6 @@ export function sendMessage(
groupedId?: string; groupedId?: string;
noWebPage?: boolean; noWebPage?: boolean;
sendAs?: ApiUser | ApiChat; sendAs?: ApiUser | ApiChat;
serverTimeOffset?: number;
shouldUpdateStickerSetsOrder?: boolean; shouldUpdateStickerSetsOrder?: boolean;
}, },
onProgress?: ApiOnProgress, onProgress?: ApiOnProgress,
@ -253,7 +252,6 @@ export function sendMessage(
groupedId, groupedId,
scheduledAt, scheduledAt,
sendAs, sendAs,
serverTimeOffset,
); );
onUpdate({ onUpdate({
@ -498,16 +496,14 @@ export async function editMessage({
text, text,
entities, entities,
noWebPage, noWebPage,
serverTimeOffset,
}: { }: {
chat: ApiChat; chat: ApiChat;
message: ApiMessage; message: ApiMessage;
text: string; text: string;
entities?: ApiMessageEntity[]; entities?: ApiMessageEntity[];
noWebPage?: boolean; noWebPage?: boolean;
serverTimeOffset: number;
}) { }) {
const isScheduled = message.date * 1000 > Date.now() + serverTimeOffset * 1000; const isScheduled = message.date * 1000 > Date.now() + getServerTimeOffset() * 1000;
let messageUpdate: Partial<ApiMessage> = { let messageUpdate: Partial<ApiMessage> = {
content: { content: {
...message.content, ...message.content,
@ -780,9 +776,9 @@ export async function sendMessageAction({
} }
export async function markMessageListRead({ export async function markMessageListRead({
chat, threadId, maxId = -1, serverTimeOffset, chat, threadId, maxId = -1,
}: { }: {
chat: ApiChat; threadId: number; maxId?: number; serverTimeOffset: number; chat: ApiChat; threadId: number; maxId?: number;
}) { }) {
const isChannel = getEntityTypeById(chat.id) === 'channel'; const isChannel = getEntityTypeById(chat.id) === 'channel';
@ -807,7 +803,7 @@ export async function markMessageListRead({
} }
if (threadId === MAIN_THREAD_ID) { if (threadId === MAIN_THREAD_ID) {
void requestChatUpdate({ chat, serverTimeOffset, noLastMessage: true }); void requestChatUpdate({ chat, noLastMessage: true });
} else { } else {
void requestThreadInfoUpdate({ chat, threadId }); void requestThreadInfoUpdate({ chat, threadId });
} }
@ -1191,7 +1187,6 @@ export async function forwardMessages({
toChat, toChat,
toThreadId, toThreadId,
messages, messages,
serverTimeOffset,
isSilent, isSilent,
scheduledAt, scheduledAt,
sendAs, sendAs,
@ -1204,7 +1199,6 @@ export async function forwardMessages({
toChat: ApiChat; toChat: ApiChat;
toThreadId?: number; toThreadId?: number;
messages: ApiMessage[]; messages: ApiMessage[];
serverTimeOffset: number;
isSilent?: boolean; isSilent?: boolean;
scheduledAt?: number; scheduledAt?: number;
sendAs?: ApiUser | ApiChat; sendAs?: ApiUser | ApiChat;
@ -1221,7 +1215,6 @@ export async function forwardMessages({
toChat, toChat,
toThreadId, toThreadId,
message, message,
serverTimeOffset,
scheduledAt, scheduledAt,
noAuthors, noAuthors,
noCaptions, noCaptions,

View File

@ -251,9 +251,7 @@ export function terminateAllWebAuthorizations() {
return invokeRequest(new GramJs.account.ResetWebAuthorizations()); return invokeRequest(new GramJs.account.ResetWebAuthorizations());
} }
export async function fetchNotificationExceptions({ export async function fetchNotificationExceptions() {
serverTimeOffset,
}: { serverTimeOffset: number }) {
const result = await invokeRequest(new GramJs.account.GetNotifyExceptions({ const result = await invokeRequest(new GramJs.account.GetNotifyExceptions({
compareSound: true, compareSound: true,
}), undefined, undefined, true); }), undefined, undefined, true);
@ -269,15 +267,13 @@ export async function fetchNotificationExceptions({
return acc; return acc;
} }
acc.push(buildApiNotifyException(update.notifySettings, update.peer.peer, serverTimeOffset)); acc.push(buildApiNotifyException(update.notifySettings, update.peer.peer));
return acc; return acc;
}, [] as ApiNotifyException[]); }, [] as ApiNotifyException[]);
} }
export async function fetchNotificationSettings({ export async function fetchNotificationSettings() {
serverTimeOffset,
}: { serverTimeOffset: number }) {
const [ const [
isMutedContactSignUpNotification, isMutedContactSignUpNotification,
privateContactNotificationsSettings, privateContactNotificationsSettings,
@ -314,17 +310,17 @@ export async function fetchNotificationSettings({
hasContactJoinedNotifications: !isMutedContactSignUpNotification, hasContactJoinedNotifications: !isMutedContactSignUpNotification,
hasPrivateChatsNotifications: !( hasPrivateChatsNotifications: !(
privateSilent privateSilent
|| (typeof privateMuteUntil === 'number' && getServerTime(serverTimeOffset) < privateMuteUntil) || (typeof privateMuteUntil === 'number' && getServerTime() < privateMuteUntil)
), ),
hasPrivateChatsMessagePreview: privateShowPreviews, hasPrivateChatsMessagePreview: privateShowPreviews,
hasGroupNotifications: !( hasGroupNotifications: !(
groupSilent || (typeof groupMuteUntil === 'number' groupSilent || (typeof groupMuteUntil === 'number'
&& getServerTime(serverTimeOffset) < groupMuteUntil) && getServerTime() < groupMuteUntil)
), ),
hasGroupMessagePreview: groupShowPreviews, hasGroupMessagePreview: groupShowPreviews,
hasBroadcastNotifications: !( hasBroadcastNotifications: !(
broadcastSilent || (typeof broadcastMuteUntil === 'number' broadcastSilent || (typeof broadcastMuteUntil === 'number'
&& getServerTime(serverTimeOffset) < broadcastMuteUntil) && getServerTime() < broadcastMuteUntil)
), ),
hasBroadcastMessagePreview: broadcastShowPreviews, hasBroadcastMessagePreview: broadcastShowPreviews,
}; };

View File

@ -4,7 +4,9 @@ import type {
ApiMessage, ApiMessageExtendedMediaPreview, ApiUpdateConnectionStateType, OnApiUpdate, ApiMessage, ApiMessageExtendedMediaPreview, ApiUpdateConnectionStateType, OnApiUpdate,
} from '../types'; } from '../types';
import { DEBUG, GENERAL_TOPIC_ID } from '../../config';
import { omit, pick } from '../../util/iteratees'; import { omit, pick } from '../../util/iteratees';
import { getServerTimeOffset, setServerTimeOffset } from '../../util/serverTime';
import { import {
buildApiMessage, buildApiMessage,
buildApiMessageFromShort, buildApiMessageFromShort,
@ -39,7 +41,6 @@ import {
} from './gramjsBuilders'; } from './gramjsBuilders';
import localDb from './localDb'; import localDb from './localDb';
import { omitVirtualClassFields } from './apiBuilders/helpers'; import { omitVirtualClassFields } from './apiBuilders/helpers';
import { DEBUG, GENERAL_TOPIC_ID } from '../../config';
import { import {
addMessageToLocalDb, addMessageToLocalDb,
addEntitiesWithPhotosToLocalDb, addEntitiesWithPhotosToLocalDb,
@ -79,7 +80,6 @@ export function init(_onUpdate: OnApiUpdate) {
} }
const sentMessageIds = new Set(); const sentMessageIds = new Set();
let serverTimeOffset = 0;
// Workaround for a situation when an incorrect update comes with an undefined property `adminRights` // Workaround for a situation when an incorrect update comes with an undefined property `adminRights`
let shouldIgnoreNextChannelUpdate = false; let shouldIgnoreNextChannelUpdate = false;
const IGNORE_NEXT_CHANNEL_UPDATE_TIMEOUT = 2000; const IGNORE_NEXT_CHANNEL_UPDATE_TIMEOUT = 2000;
@ -121,7 +121,12 @@ function dispatchUserAndChatUpdates(entities: (GramJs.TypeUser | GramJs.TypeChat
export function updater(update: Update, originRequest?: GramJs.AnyRequest) { export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
if (update instanceof connection.UpdateServerTimeOffset) { if (update instanceof connection.UpdateServerTimeOffset) {
serverTimeOffset = update.timeOffset; setServerTimeOffset(update.timeOffset);
onUpdate({
'@type': 'updateServerTimeOffset',
serverTimeOffset: update.timeOffset,
});
} else if (update instanceof connection.UpdateConnectionState) { } else if (update instanceof connection.UpdateConnectionState) {
let connectionState: ApiUpdateConnectionStateType; let connectionState: ApiUpdateConnectionStateType;
@ -423,7 +428,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
}, },
}); });
} else { } else {
const currentDate = Date.now() / 1000 + serverTimeOffset; const currentDate = Date.now() / 1000 + getServerTimeOffset();
const message = buildApiMessageFromNotification(update, currentDate); const message = buildApiMessageFromNotification(update, currentDate);
if (isMessageWithMedia(update)) { if (isMessageWithMedia(update)) {
@ -478,7 +483,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
sentMessageIds.add(update.id); sentMessageIds.add(update.id);
// Edge case for "Send When Online" // Edge case for "Send When Online"
const isAlreadySent = 'date' in update && update.date * 1000 < Date.now() + serverTimeOffset * 1000; const isAlreadySent = 'date' in update && update.date * 1000 < Date.now() + getServerTimeOffset() * 1000;
onUpdate({ onUpdate({
'@type': localMessage.isScheduled && !isAlreadySent '@type': localMessage.isScheduled && !isAlreadySent
@ -675,7 +680,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
) { ) {
onUpdate({ onUpdate({
'@type': 'updateNotifyExceptions', '@type': 'updateNotifyExceptions',
...buildApiNotifyException(update.notifySettings, update.peer.peer, serverTimeOffset), ...buildApiNotifyException(update.notifySettings, update.peer.peer),
}); });
} else if ( } else if (
update instanceof GramJs.UpdateNotifySettings update instanceof GramJs.UpdateNotifySettings
@ -684,7 +689,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateTopicNotifyExceptions', '@type': 'updateTopicNotifyExceptions',
...buildApiNotifyExceptionTopic( ...buildApiNotifyExceptionTopic(
update.notifySettings, update.peer.peer, update.peer.topMsgId, serverTimeOffset, update.notifySettings, update.peer.peer, update.peer.topMsgId,
), ),
}); });
} else if ( } else if (
@ -707,7 +712,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
onUpdate({ onUpdate({
'@type': 'updateChatTypingStatus', '@type': 'updateChatTypingStatus',
id, id,
typingStatus: buildChatTypingStatus(update, serverTimeOffset), typingStatus: buildChatTypingStatus(update),
}); });
} }
} else if (update instanceof GramJs.UpdateChannelUserTyping) { } else if (update instanceof GramJs.UpdateChannelUserTyping) {
@ -717,7 +722,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
'@type': 'updateChatTypingStatus', '@type': 'updateChatTypingStatus',
id, id,
threadId: update.topMsgId, threadId: update.topMsgId,
typingStatus: buildChatTypingStatus(update, serverTimeOffset), typingStatus: buildChatTypingStatus(update),
}); });
} else if (update instanceof GramJs.UpdateChannel) { } else if (update instanceof GramJs.UpdateChannel) {
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
@ -907,7 +912,7 @@ export function updater(update: Update, originRequest?: GramJs.AnyRequest) {
'@type': 'updateNotifySettings', '@type': 'updateNotifySettings',
peerType, peerType,
isSilent: Boolean(silent isSilent: Boolean(silent
|| (typeof muteUntil === 'number' && Date.now() + serverTimeOffset * 1000 < muteUntil * 1000)), || (typeof muteUntil === 'number' && Date.now() + getServerTimeOffset() * 1000 < muteUntil * 1000)),
shouldShowPreviews: Boolean(showPreviews), shouldShowPreviews: Boolean(showPreviews),
}); });
} else if (update instanceof GramJs.UpdatePeerBlocked) { } else if (update instanceof GramJs.UpdatePeerBlocked) {

View File

@ -48,7 +48,6 @@ type StateProps =
isSavedMessages?: boolean; isSavedMessages?: boolean;
animationLevel: AnimationLevel; animationLevel: AnimationLevel;
areMessagesLoaded: boolean; areMessagesLoaded: boolean;
serverTimeOffset: number;
} }
& Pick<GlobalState, 'lastSyncTime'>; & Pick<GlobalState, 'lastSyncTime'>;
@ -71,7 +70,6 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
areMessagesLoaded, areMessagesLoaded,
animationLevel, animationLevel,
lastSyncTime, lastSyncTime,
serverTimeOffset,
adminMember, adminMember,
}) => { }) => {
const { const {
@ -133,7 +131,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
return ( return (
<span className={buildClassName('status', isUserOnline(user, userStatus) && 'online')}> <span className={buildClassName('status', isUserOnline(user, userStatus) && 'online')}>
{mainUsername && <span className="handle">{mainUsername}</span>} {mainUsername && <span className="handle">{mainUsername}</span>}
<span className="user-status" dir="auto">{getUserStatus(lang, user, userStatus, serverTimeOffset)}</span> <span className="user-status" dir="auto">{getUserStatus(lang, user, userStatus)}</span>
</span> </span>
); );
} }
@ -188,7 +186,7 @@ const PrivateChatInfo: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { userId, forceShowSelf }): StateProps => { (global, { userId, forceShowSelf }): StateProps => {
const { lastSyncTime, serverTimeOffset } = global; const { lastSyncTime } = global;
const user = selectUser(global, userId); const user = selectUser(global, userId);
const userStatus = selectUserStatus(global, userId); const userStatus = selectUserStatus(global, userId);
const isSavedMessages = !forceShowSelf && user && user.isSelf; const isSavedMessages = !forceShowSelf && user && user.isSelf;
@ -200,7 +198,6 @@ export default memo(withGlobal<OwnProps>(
userStatus, userStatus,
isSavedMessages, isSavedMessages,
areMessagesLoaded, areMessagesLoaded,
serverTimeOffset,
animationLevel: global.settings.byKey.animationLevel, animationLevel: global.settings.byKey.animationLevel,
}; };
}, },

View File

@ -46,7 +46,6 @@ type StateProps =
chat?: ApiChat; chat?: ApiChat;
isSavedMessages?: boolean; isSavedMessages?: boolean;
animationLevel: AnimationLevel; animationLevel: AnimationLevel;
serverTimeOffset: number;
mediaId?: number; mediaId?: number;
avatarOwnerId?: string; avatarOwnerId?: string;
topic?: ApiTopic; topic?: ApiTopic;
@ -66,7 +65,6 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
isSavedMessages, isSavedMessages,
connectionState, connectionState,
animationLevel, animationLevel,
serverTimeOffset,
mediaId, mediaId,
avatarOwnerId, avatarOwnerId,
topic, topic,
@ -227,7 +225,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
if (user) { if (user) {
return ( return (
<div className={buildClassName(styles.status, 'status', isUserOnline(user, userStatus) && 'online')}> <div className={buildClassName(styles.status, 'status', isUserOnline(user, userStatus) && 'online')}>
<span className="user-status" dir="auto">{getUserStatus(lang, user, userStatus, serverTimeOffset)}</span> <span className="user-status" dir="auto">{getUserStatus(lang, user, userStatus)}</span>
</div> </div>
); );
} }
@ -296,7 +294,7 @@ const ProfileInfo: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { userId, forceShowSelf }): StateProps => { (global, { userId, forceShowSelf }): StateProps => {
const { connectionState, serverTimeOffset } = global; const { connectionState } = global;
const user = selectUser(global, userId); const user = selectUser(global, userId);
const userStatus = selectUserStatus(global, userId); const userStatus = selectUserStatus(global, userId);
const chat = selectChat(global, userId); const chat = selectChat(global, userId);
@ -314,7 +312,6 @@ export default memo(withGlobal<OwnProps>(
chat, chat,
isSavedMessages, isSavedMessages,
animationLevel, animationLevel,
serverTimeOffset,
mediaId, mediaId,
avatarOwnerId, avatarOwnerId,
...(topic && { ...(topic && {

View File

@ -26,7 +26,6 @@ type StateProps = {
usersById: Record<string, ApiUser>; usersById: Record<string, ApiUser>;
userStatusesById: Record<string, ApiUserStatus>; userStatusesById: Record<string, ApiUserStatus>;
contactIds?: string[]; contactIds?: string[];
serverTimeOffset: number;
}; };
const ContactList: FC<OwnProps & StateProps> = ({ const ContactList: FC<OwnProps & StateProps> = ({
@ -35,7 +34,6 @@ const ContactList: FC<OwnProps & StateProps> = ({
usersById, usersById,
userStatusesById, userStatusesById,
contactIds, contactIds,
serverTimeOffset,
onReset, onReset,
}) => { }) => {
const { const {
@ -61,8 +59,8 @@ const ContactList: FC<OwnProps & StateProps> = ({
const filteredIds = filterUsersByName(contactIds, usersById, filter); const filteredIds = filterUsersByName(contactIds, usersById, filter);
return sortUserIds(filteredIds, usersById, userStatusesById, undefined, serverTimeOffset); return sortUserIds(filteredIds, usersById, userStatusesById);
}, [contactIds, filter, usersById, userStatusesById, serverTimeOffset]); }, [contactIds, filter, usersById, userStatusesById]);
const [viewportIds, getMore] = useInfiniteScroll(undefined, listIds, Boolean(filter)); const [viewportIds, getMore] = useInfiniteScroll(undefined, listIds, Boolean(filter));
@ -108,7 +106,6 @@ export default memo(withGlobal<OwnProps>(
usersById, usersById,
userStatusesById, userStatusesById,
contactIds, contactIds,
serverTimeOffset: global.serverTimeOffset,
}; };
}, },
)(ContactList)); )(ContactList));

View File

@ -35,7 +35,6 @@ type StateProps = {
user?: ApiUser; user?: ApiUser;
userStatus?: ApiUserStatus; userStatus?: ApiUserStatus;
phoneCodeList: ApiCountryCode[]; phoneCodeList: ApiCountryCode[];
serverTimeOffset?: number;
}; };
const NewContactModal: FC<OwnProps & StateProps> = ({ const NewContactModal: FC<OwnProps & StateProps> = ({
@ -45,7 +44,6 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
user, user,
userStatus, userStatus,
phoneCodeList, phoneCodeList,
serverTimeOffset,
}) => { }) => {
const { updateContact, importContact, closeNewContactDialog } = getActions(); const { updateContact, importContact, closeNewContactDialog } = getActions();
@ -130,7 +128,7 @@ const NewContactModal: FC<OwnProps & StateProps> = ({
: lang('MobileHidden')} : lang('MobileHidden')}
</p> </p>
<span className="NewContactModal__user-status" dir="auto"> <span className="NewContactModal__user-status" dir="auto">
{getUserStatus(lang, renderingUser!, userStatus, serverTimeOffset!)} {getUserStatus(lang, renderingUser!, userStatus)}
</span> </span>
</div> </div>
</div> </div>
@ -232,7 +230,6 @@ export default memo(withGlobal<OwnProps>(
return { return {
user: userId ? selectUser(global, userId) : undefined, user: userId ? selectUser(global, userId) : undefined,
userStatus: userId ? selectUserStatus(global, userId) : undefined, userStatus: userId ? selectUserStatus(global, userId) : undefined,
serverTimeOffset: global.serverTimeOffset,
phoneCodeList: global.countryList.phoneCodes, phoneCodeList: global.countryList.phoneCodes,
}; };
}, },

View File

@ -2,7 +2,7 @@ import type { FC } from '../../../lib/teact/teact';
import React, { import React, {
memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global'; import { getActions, withGlobal } from '../../../global';
import type { GlobalState, MessageListType } from '../../../global/types'; import type { GlobalState, MessageListType } from '../../../global/types';
import type { import type {
@ -635,12 +635,9 @@ const Composer: FC<OwnProps & StateProps> = ({
const checkSlowMode = useCallback(() => { const checkSlowMode = useCallback(() => {
if (slowMode && !isAdmin) { if (slowMode && !isAdmin) {
// No need to subscribe on updates in `mapStateToProps`
const { serverTimeOffset } = getGlobal();
const messageInput = document.querySelector<HTMLDivElement>(EDITABLE_INPUT_CSS_SELECTOR); const messageInput = document.querySelector<HTMLDivElement>(EDITABLE_INPUT_CSS_SELECTOR);
const nowSeconds = getServerTime(serverTimeOffset); const nowSeconds = getServerTime();
const secondsSinceLastMessage = lastMessageSendTimeSeconds.current const secondsSinceLastMessage = lastMessageSendTimeSeconds.current
&& Math.floor(nowSeconds - lastMessageSendTimeSeconds.current); && Math.floor(nowSeconds - lastMessageSendTimeSeconds.current);
const nextSendDateNotReached = slowMode.nextSendDate && slowMode.nextSendDate > nowSeconds; const nextSendDateNotReached = slowMode.nextSendDate && slowMode.nextSendDate > nowSeconds;
@ -692,10 +689,7 @@ const Composer: FC<OwnProps & StateProps> = ({
shouldGroupMessages: sendGrouped, shouldGroupMessages: sendGrouped,
}); });
// No need to subscribe on updates in `mapStateToProps` lastMessageSendTimeSeconds.current = getServerTime();
const { serverTimeOffset } = getGlobal();
lastMessageSendTimeSeconds.current = getServerTime(serverTimeOffset);
clearDraft({ chatId, localOnly: true }); clearDraft({ chatId, localOnly: true });
@ -738,9 +732,6 @@ const Composer: FC<OwnProps & StateProps> = ({
return; return;
} }
// No need to subscribe on updates in `mapStateToProps`
const { serverTimeOffset } = getGlobal();
if (!validateTextLength(text)) return; if (!validateTextLength(text)) return;
const messageInput = document.querySelector<HTMLDivElement>(EDITABLE_INPUT_CSS_SELECTOR); const messageInput = document.querySelector<HTMLDivElement>(EDITABLE_INPUT_CSS_SELECTOR);
@ -764,7 +755,7 @@ const Composer: FC<OwnProps & StateProps> = ({
}); });
} }
lastMessageSendTimeSeconds.current = getServerTime(serverTimeOffset); lastMessageSendTimeSeconds.current = getServerTime();
clearDraft({ chatId, localOnly: true }); clearDraft({ chatId, localOnly: true });

View File

@ -55,7 +55,6 @@ type OwnProps = {
isInSelectMode?: boolean; isInSelectMode?: boolean;
isSelected?: boolean; isSelected?: boolean;
theme: ISettings['theme']; theme: ISettings['theme'];
serverTimeOffset: number;
}; };
const Location: FC<OwnProps> = ({ const Location: FC<OwnProps> = ({
@ -65,7 +64,6 @@ const Location: FC<OwnProps> = ({
isInSelectMode, isInSelectMode,
isSelected, isSelected,
theme, theme,
serverTimeOffset,
}) => { }) => {
const { openUrl } = getActions(); const { openUrl } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -78,7 +76,7 @@ const Location: FC<OwnProps> = ({
const location = getMessageLocation(message)!; const location = getMessageLocation(message)!;
const { type, geo } = location; const { type, geo } = location;
const serverTime = getServerTime(serverTimeOffset); const serverTime = getServerTime();
const isExpired = isGeoLiveExpired(message, serverTime); const isExpired = isGeoLiveExpired(message, serverTime);
const secondsBeforeEnd = (type === 'geoLive' && !isExpired) ? message.date + location.period - serverTime const secondsBeforeEnd = (type === 'geoLive' && !isExpired) ? message.date + location.period - serverTime
: undefined; : undefined;
@ -122,7 +120,7 @@ const Location: FC<OwnProps> = ({
const svgEl = countdownEl.lastElementChild; const svgEl = countdownEl.lastElementChild;
const timerEl = countdownEl.firstElementChild as SVGElement; const timerEl = countdownEl.firstElementChild as SVGElement;
const timeLeft = message.date + location.period - getServerTime(serverTimeOffset); const timeLeft = message.date + location.period - getServerTime();
const strokeDashOffset = (1 - timeLeft / location.period) * circumference; const strokeDashOffset = (1 - timeLeft / location.period) * circumference;
const text = formatCountdownShort(lang, timeLeft * 1000); const text = formatCountdownShort(lang, timeLeft * 1000);
@ -139,7 +137,7 @@ const Location: FC<OwnProps> = ({
timerEl.textContent = text; timerEl.textContent = text;
svgEl.firstElementChild!.setAttribute('stroke-dashoffset', `-${strokeDashOffset}`); svgEl.firstElementChild!.setAttribute('stroke-dashoffset', `-${strokeDashOffset}`);
} }
}, [type, message.date, location, serverTimeOffset, lang]); }, [type, message.date, location, lang]);
useLayoutEffect(() => { useLayoutEffect(() => {
if (countdownRef.current) { if (countdownRef.current) {

View File

@ -201,7 +201,6 @@ type StateProps = {
isGroup?: boolean; isGroup?: boolean;
canReply?: boolean; canReply?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
serverTimeOffset: number;
highlight?: string; highlight?: string;
animatedEmoji?: string; animatedEmoji?: string;
animatedCustomEmoji?: string; animatedCustomEmoji?: string;
@ -297,7 +296,6 @@ const Message: FC<OwnProps & StateProps> = ({
isGroup, isGroup,
canReply, canReply,
lastSyncTime, lastSyncTime,
serverTimeOffset,
highlight, highlight,
animatedEmoji, animatedEmoji,
animatedCustomEmoji, animatedCustomEmoji,
@ -546,7 +544,7 @@ const Message: FC<OwnProps & StateProps> = ({
hasComments: repliesThreadInfo && repliesThreadInfo.messagesCount > 0, hasComments: repliesThreadInfo && repliesThreadInfo.messagesCount > 0,
hasActionButton: canForward || canFocus, hasActionButton: canForward || canFocus,
hasReactions, hasReactions,
isGeoLiveActive: location?.type === 'geoLive' && !isGeoLiveExpired(message, getServerTime(serverTimeOffset)), isGeoLiveActive: location?.type === 'geoLive' && !isGeoLiveExpired(message, getServerTime()),
withVoiceTranscription, withVoiceTranscription,
}); });
@ -959,7 +957,6 @@ const Message: FC<OwnProps & StateProps> = ({
isSelected={isSelected} isSelected={isSelected}
theme={theme} theme={theme}
peer={sender} peer={sender}
serverTimeOffset={serverTimeOffset}
/> />
)} )}
</div> </div>
@ -1174,7 +1171,7 @@ const Message: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, ownProps): StateProps => { (global, ownProps): StateProps => {
const { const {
focusedMessage, forwardMessages, lastSyncTime, serverTimeOffset, focusedMessage, forwardMessages, lastSyncTime,
} = global; } = global;
const { const {
message, album, withSenderName, withAvatar, threadId, messageListType, isLastInDocumentGroup, isFirstInGroup, message, album, withSenderName, withAvatar, threadId, messageListType, isLastInDocumentGroup, isFirstInGroup,
@ -1280,7 +1277,6 @@ export default memo(withGlobal<OwnProps>(
isGroup, isGroup,
canReply, canReply,
lastSyncTime, lastSyncTime,
serverTimeOffset,
highlight, highlight,
animatedEmoji, animatedEmoji,
animatedCustomEmoji, animatedCustomEmoji,

View File

@ -18,6 +18,7 @@ import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntit
import { formatMediaDuration } from '../../../util/dateFormat'; import { formatMediaDuration } from '../../../util/dateFormat';
import type { LangFn } from '../../../hooks/useLang'; import type { LangFn } from '../../../hooks/useLang';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { getServerTimeOffset } from '../../../util/serverTime';
import CheckboxGroup from '../../ui/CheckboxGroup'; import CheckboxGroup from '../../ui/CheckboxGroup';
import RadioGroup from '../../ui/RadioGroup'; import RadioGroup from '../../ui/RadioGroup';
@ -37,7 +38,6 @@ type OwnProps = {
type StateProps = { type StateProps = {
recentVoterIds?: number[]; recentVoterIds?: number[];
usersById: Record<string, ApiUser>; usersById: Record<string, ApiUser>;
serverTimeOffset: number;
}; };
const SOLUTION_CONTAINER_ID = '#middle-column-portals'; const SOLUTION_CONTAINER_ID = '#middle-column-portals';
@ -50,7 +50,6 @@ const Poll: FC<OwnProps & StateProps> = ({
recentVoterIds, recentVoterIds,
usersById, usersById,
onSendVote, onSendVote,
serverTimeOffset,
}) => { }) => {
const { loadMessage, openPollResults, requestConfetti } = getActions(); const { loadMessage, openPollResults, requestConfetti } = getActions();
@ -62,7 +61,7 @@ const Poll: FC<OwnProps & StateProps> = ({
const [wasSubmitted, setWasSubmitted] = useState<boolean>(false); const [wasSubmitted, setWasSubmitted] = useState<boolean>(false);
const [closePeriod, setClosePeriod] = useState<number>( const [closePeriod, setClosePeriod] = useState<number>(
!summary.closed && summary.closeDate && summary.closeDate > 0 !summary.closed && summary.closeDate && summary.closeDate > 0
? Math.min(summary.closeDate - Math.floor(Date.now() / 1000) + serverTimeOffset, summary.closePeriod!) ? Math.min(summary.closeDate - Math.floor(Date.now() / 1000) + getServerTimeOffset(), summary.closePeriod!)
: 0, : 0,
); );
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -362,7 +361,7 @@ function stopPropagation(e: React.MouseEvent<HTMLDivElement>) {
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { poll }) => { (global, { poll }) => {
const { recentVoterIds } = poll.results; const { recentVoterIds } = poll.results;
const { serverTimeOffset, users: { byId: usersById } } = global; const { users: { byId: usersById } } = global;
if (!recentVoterIds || recentVoterIds.length === 0) { if (!recentVoterIds || recentVoterIds.length === 0) {
return {}; return {};
} }
@ -370,7 +369,6 @@ export default memo(withGlobal<OwnProps>(
return { return {
recentVoterIds, recentVoterIds,
usersById, usersById,
serverTimeOffset,
}; };
}, },
)(Poll)); )(Poll));

View File

@ -98,7 +98,6 @@ type StateProps = {
isRightColumnShown: boolean; isRightColumnShown: boolean;
isRestricted?: boolean; isRestricted?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
serverTimeOffset: number;
activeDownloadIds: number[]; activeDownloadIds: number[];
isChatProtected?: boolean; isChatProtected?: boolean;
}; };
@ -141,7 +140,6 @@ const Profile: FC<OwnProps & StateProps> = ({
isRestricted, isRestricted,
lastSyncTime, lastSyncTime,
activeDownloadIds, activeDownloadIds,
serverTimeOffset,
isChatProtected, isChatProtected,
}) => { }) => {
const { const {
@ -197,7 +195,6 @@ const Profile: FC<OwnProps & StateProps> = ({
chatMessages, chatMessages,
foundIds, foundIds,
lastSyncTime, lastSyncTime,
serverTimeOffset,
topicId, topicId,
); );
const isFirstTab = resultType === 'members' || (!hasMembersTab && resultType === 'media'); const isFirstTab = resultType === 'members' || (!hasMembersTab && resultType === 'media');
@ -583,7 +580,6 @@ export default memo(withGlobal<OwnProps>(
isRightColumnShown: selectIsRightColumnShown(global), isRightColumnShown: selectIsRightColumnShown(global),
isRestricted: chat?.isRestricted, isRestricted: chat?.isRestricted,
lastSyncTime: global.lastSyncTime, lastSyncTime: global.lastSyncTime,
serverTimeOffset: global.serverTimeOffset,
activeDownloadIds, activeDownloadIds,
usersById, usersById,
userStatusesById, userStatusesById,

View File

@ -24,7 +24,6 @@ export default function useProfileViewportIds(
chatMessages?: Record<number, ApiMessage>, chatMessages?: Record<number, ApiMessage>,
foundIds?: number[], foundIds?: number[],
lastSyncTime?: number, lastSyncTime?: number,
serverTimeOffset = 0,
topicId?: number, topicId?: number,
) { ) {
const resultType = tabType === 'members' || !mediaSearchType ? tabType : mediaSearchType; const resultType = tabType === 'members' || !mediaSearchType ? tabType : mediaSearchType;
@ -38,10 +37,8 @@ export default function useProfileViewportIds(
groupChatMembers.map(({ userId }) => userId), groupChatMembers.map(({ userId }) => userId),
usersById, usersById,
userStatusesById, userStatusesById,
undefined,
serverTimeOffset,
); );
}, [groupChatMembers, serverTimeOffset, usersById, userStatusesById]); }, [groupChatMembers, usersById, userStatusesById]);
const chatIds = useMemo(() => { const chatIds = useMemo(() => {
if (!commonChatIds || !chatsById) { if (!commonChatIds || !chatsById) {

View File

@ -29,7 +29,6 @@ type StateProps = {
user?: ApiUser; user?: ApiUser;
isSavedMessages?: boolean; isSavedMessages?: boolean;
animationLevel: AnimationLevel; animationLevel: AnimationLevel;
serverTimeOffset: number;
}; };
const JoinRequest: FC<OwnProps & StateProps> = ({ const JoinRequest: FC<OwnProps & StateProps> = ({
@ -40,7 +39,6 @@ const JoinRequest: FC<OwnProps & StateProps> = ({
isChannel, isChannel,
user, user,
animationLevel, animationLevel,
serverTimeOffset,
}) => { }) => {
const { openChat, hideChatJoinRequest } = getActions(); const { openChat, hideChatJoinRequest } = getActions();
@ -48,7 +46,7 @@ const JoinRequest: FC<OwnProps & StateProps> = ({
const lang = useLang(); const lang = useLang();
const fullName = getUserFullName(user); const fullName = getUserFullName(user);
const fixedDate = (date - getServerTime(serverTimeOffset)) * 1000 + Date.now(); const fixedDate = (date - getServerTime()) * 1000 + Date.now();
const dateString = isToday(new Date(fixedDate)) const dateString = isToday(new Date(fixedDate))
? formatTime(lang, fixedDate) : formatHumanDate(lang, fixedDate, true, false, true); ? formatTime(lang, fixedDate) : formatHumanDate(lang, fixedDate, true, false, true);
@ -102,7 +100,6 @@ export default memo(withGlobal<OwnProps>(
return { return {
user, user,
animationLevel: global.settings.byKey.animationLevel, animationLevel: global.settings.byKey.animationLevel,
serverTimeOffset: global.serverTimeOffset,
}; };
}, },
)(JoinRequest)); )(JoinRequest));

View File

@ -45,7 +45,6 @@ type StateProps = {
isSearching?: boolean; isSearching?: boolean;
localUserIds?: string[]; localUserIds?: string[];
globalUserIds?: string[]; globalUserIds?: string[];
serverTimeOffset: number;
currentUserId?: string; currentUserId?: string;
canDeleteMembers?: boolean; canDeleteMembers?: boolean;
isBasicGroup?: boolean; isBasicGroup?: boolean;
@ -65,7 +64,6 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
localUserIds, localUserIds,
isSearching, isSearching,
searchQuery, searchQuery,
serverTimeOffset,
currentUserId, currentUserId,
canDeleteMembers, canDeleteMembers,
isBasicGroup, isBasicGroup,
@ -100,12 +98,10 @@ const ManageGroupMembers: FC<OwnProps & StateProps> = ({
members.map(({ userId }) => userId), members.map(({ userId }) => userId),
usersById, usersById,
userStatusesById, userStatusesById,
undefined,
serverTimeOffset,
); );
return noAdmins ? userIds.filter((userId) => !adminIds.includes(userId)) : userIds; return noAdmins ? userIds.filter((userId) => !adminIds.includes(userId)) : userIds;
}, [members, userStatusesById, serverTimeOffset, noAdmins, adminIds]); }, [members, userStatusesById, noAdmins, adminIds]);
const displayedIds = useMemo(() => { const displayedIds = useMemo(() => {
// No need for expensive global updates on users, so we avoid them // No need for expensive global updates on users, so we avoid them
@ -282,7 +278,6 @@ export default memo(withGlobal<OwnProps>(
globalUserIds, globalUserIds,
localUserIds, localUserIds,
canDeleteMembers, canDeleteMembers,
serverTimeOffset: global.serverTimeOffset,
currentUserId: global.currentUserId, currentUserId: global.currentUserId,
}; };
}, },

View File

@ -26,7 +26,6 @@ type StateProps = {
userStatusesById: Record<string, ApiUserStatus>; userStatusesById: Record<string, ApiUserStatus>;
members?: ApiChatMember[]; members?: ApiChatMember[];
isChannel?: boolean; isChannel?: boolean;
serverTimeOffset: number;
}; };
const ManageGroupUserPermissionsCreate: FC<OwnProps & StateProps> = ({ const ManageGroupUserPermissionsCreate: FC<OwnProps & StateProps> = ({
@ -38,7 +37,6 @@ const ManageGroupUserPermissionsCreate: FC<OwnProps & StateProps> = ({
onChatMemberSelect, onChatMemberSelect,
onClose, onClose,
isActive, isActive,
serverTimeOffset,
}) => { }) => {
useHistoryBack({ useHistoryBack({
isActive, isActive,
@ -54,10 +52,8 @@ const ManageGroupUserPermissionsCreate: FC<OwnProps & StateProps> = ({
members.filter((member) => !member.isOwner).map(({ userId }) => userId), members.filter((member) => !member.isOwner).map(({ userId }) => userId),
usersById, usersById,
userStatusesById, userStatusesById,
undefined,
serverTimeOffset,
); );
}, [members, serverTimeOffset, usersById, userStatusesById]); }, [members, usersById, userStatusesById]);
const handleExceptionMemberClick = useCallback((memberId: string) => { const handleExceptionMemberClick = useCallback((memberId: string) => {
onChatMemberSelect(memberId); onChatMemberSelect(memberId);
@ -105,7 +101,6 @@ export default memo(withGlobal<OwnProps>(
usersById, usersById,
userStatusesById, userStatusesById,
isChannel, isChannel,
serverTimeOffset: global.serverTimeOffset,
}; };
}, },
)(ManageGroupUserPermissionsCreate)); )(ManageGroupUserPermissionsCreate));

View File

@ -37,14 +37,12 @@ type OwnProps = {
type StateProps = { type StateProps = {
editingInvite?: ApiExportedInvite; editingInvite?: ApiExportedInvite;
serverTimeOffset: number;
}; };
const ManageInvite: FC<OwnProps & StateProps> = ({ const ManageInvite: FC<OwnProps & StateProps> = ({
chatId, chatId,
editingInvite, editingInvite,
isActive, isActive,
serverTimeOffset,
onClose, onClose,
onScreenSelect, onScreenSelect,
}) => { }) => {
@ -71,7 +69,7 @@ const ManageInvite: FC<OwnProps & StateProps> = ({
setTitle(''); setTitle('');
setSelectedExpireOption('unlimited'); setSelectedExpireOption('unlimited');
setSelectedUsageOption('0'); setSelectedUsageOption('0');
setCustomExpireDate(getServerTime(serverTimeOffset) * 1000 + DEFAULT_CUSTOM_EXPIRE_DATE); setCustomExpireDate(getServerTime() * 1000 + DEFAULT_CUSTOM_EXPIRE_DATE);
setCustomUsageLimit(10); setCustomUsageLimit(10);
setIsRequestNeeded(false); setIsRequestNeeded(false);
} else { } else {
@ -84,7 +82,7 @@ const ManageInvite: FC<OwnProps & StateProps> = ({
setCustomUsageLimit(usageLimit); setCustomUsageLimit(usageLimit);
} }
if (expireDate) { if (expireDate) {
const minSafeDate = getServerTime(serverTimeOffset) + DEFAULT_CUSTOM_EXPIRE_DATE; const minSafeDate = getServerTime() + DEFAULT_CUSTOM_EXPIRE_DATE;
setSelectedExpireOption('custom'); setSelectedExpireOption('custom');
setCustomExpireDate(Math.max(expireDate, minSafeDate) * 1000); setCustomExpireDate(Math.max(expireDate, minSafeDate) * 1000);
} }
@ -92,7 +90,7 @@ const ManageInvite: FC<OwnProps & StateProps> = ({
setIsRequestNeeded(true); setIsRequestNeeded(true);
} }
} }
}, [editingInvite, serverTimeOffset]); }, [editingInvite]);
const handleIsRequestChange = useCallback((e: ChangeEvent<HTMLInputElement>) => { const handleIsRequestChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setIsRequestNeeded(e.target.checked); setIsRequestNeeded(e.target.checked);
@ -117,12 +115,12 @@ const ManageInvite: FC<OwnProps & StateProps> = ({
let expireDate; let expireDate;
switch (selectedExpireOption) { switch (selectedExpireOption) {
case 'custom': case 'custom':
expireDate = getServerTime(serverTimeOffset) + (customExpireDate - Date.now()) / 1000; expireDate = getServerTime() + (customExpireDate - Date.now()) / 1000;
break; break;
case 'hour': case 'hour':
case 'day': case 'day':
case 'week': case 'week':
expireDate = getServerTime(serverTimeOffset) + DEFAULT_EXPIRE_DATE[selectedExpireOption] / 1000; expireDate = getServerTime() + DEFAULT_EXPIRE_DATE[selectedExpireOption] / 1000;
break; break;
case 'unlimited': case 'unlimited':
expireDate = 0; expireDate = 0;
@ -153,7 +151,6 @@ const ManageInvite: FC<OwnProps & StateProps> = ({
}, [ }, [
chatId, customExpireDate, customUsageLimit, editExportedChatInvite, editingInvite, chatId, customExpireDate, customUsageLimit, editExportedChatInvite, editingInvite,
exportChatInvite, isRequestNeeded, selectedExpireOption, selectedUsageOption, title, onScreenSelect, exportChatInvite, isRequestNeeded, selectedExpireOption, selectedUsageOption, title, onScreenSelect,
serverTimeOffset,
]); ]);
return ( return (
@ -272,7 +269,6 @@ export default memo(withGlobal<OwnProps>(
return { return {
editingInvite, editingInvite,
serverTimeOffset: global.serverTimeOffset,
}; };
}, },
)(ManageInvite)); )(ManageInvite));

View File

@ -29,7 +29,6 @@ type StateProps = {
requesters?: ApiChatInviteImporter[]; requesters?: ApiChatInviteImporter[];
admin?: ApiUser; admin?: ApiUser;
isChannel?: boolean; isChannel?: boolean;
serverTimeOffset: number;
}; };
const ManageInviteInfo: FC<OwnProps & StateProps> = ({ const ManageInviteInfo: FC<OwnProps & StateProps> = ({
@ -39,7 +38,6 @@ const ManageInviteInfo: FC<OwnProps & StateProps> = ({
requesters, requesters,
isChannel, isChannel,
isActive, isActive,
serverTimeOffset,
onClose, onClose,
}) => { }) => {
const { const {
@ -53,8 +51,8 @@ const ManageInviteInfo: FC<OwnProps & StateProps> = ({
const { const {
usage = 0, usageLimit, link, adminId, usage = 0, usageLimit, link, adminId,
} = invite || {}; } = invite || {};
const expireDate = invite?.expireDate && (invite.expireDate - getServerTime(serverTimeOffset)) * 1000 + Date.now(); const expireDate = invite?.expireDate && (invite.expireDate - getServerTime()) * 1000 + Date.now();
const isExpired = ((invite?.expireDate || 0) - getServerTime(serverTimeOffset)) < 0; const isExpired = ((invite?.expireDate || 0) - getServerTime()) < 0;
useEffect(() => { useEffect(() => {
if (link) { if (link) {
@ -191,7 +189,6 @@ export default memo(withGlobal<OwnProps>(
importers, importers,
requesters, requesters,
isChannel, isChannel,
serverTimeOffset: global.serverTimeOffset,
}; };
}, },
)(ManageInviteInfo)); )(ManageInviteInfo));

View File

@ -41,7 +41,6 @@ type StateProps = {
isChannel?: boolean; isChannel?: boolean;
exportedInvites?: ApiExportedInvite[]; exportedInvites?: ApiExportedInvite[];
revokedExportedInvites?: ApiExportedInvite[]; revokedExportedInvites?: ApiExportedInvite[];
serverTimeOffset: number;
}; };
const BULLET = '\u2022'; const BULLET = '\u2022';
@ -61,7 +60,6 @@ const ManageInvites: FC<OwnProps & StateProps> = ({
revokedExportedInvites, revokedExportedInvites,
isActive, isActive,
isChannel, isChannel,
serverTimeOffset,
onClose, onClose,
onScreenSelect, onScreenSelect,
}) => { }) => {
@ -91,9 +89,9 @@ const ManageInvites: FC<OwnProps & StateProps> = ({
if (!exportedInvites) return undefined; if (!exportedInvites) return undefined;
return exportedInvites return exportedInvites
.some(({ expireDate }) => ( .some(({ expireDate }) => (
expireDate && (expireDate - getServerTime(serverTimeOffset) < MILLISECONDS_IN_DAY / 1000) expireDate && (expireDate - getServerTime() < MILLISECONDS_IN_DAY / 1000)
)); ));
}, [exportedInvites, serverTimeOffset]); }, [exportedInvites]);
const forceUpdate = useForceUpdate(); const forceUpdate = useForceUpdate();
useInterval(() => { useInterval(() => {
forceUpdate(); forceUpdate();
@ -211,7 +209,7 @@ const ManageInvites: FC<OwnProps & StateProps> = ({
if (usageLimit !== undefined && usage === usageLimit) { if (usageLimit !== undefined && usage === usageLimit) {
text += ` ${BULLET} ${lang('LinkLimitReached')}`; text += ` ${BULLET} ${lang('LinkLimitReached')}`;
} else if (expireDate) { } else if (expireDate) {
const diff = (expireDate - getServerTime(serverTimeOffset)) * 1000; const diff = (expireDate - getServerTime()) * 1000;
text += ` ${BULLET} `; text += ` ${BULLET} `;
if (diff > 0) { if (diff > 0) {
text += lang('InviteLink.ExpiresIn', formatCountdown(lang, diff)); text += lang('InviteLink.ExpiresIn', formatCountdown(lang, diff));
@ -236,7 +234,7 @@ const ManageInvites: FC<OwnProps & StateProps> = ({
return 'link-status-icon-green'; return 'link-status-icon-green';
} }
if (expireDate) { if (expireDate) {
const diff = (expireDate - getServerTime(serverTimeOffset)) * 1000; const diff = (expireDate - getServerTime()) * 1000;
if (diff <= 0) { if (diff <= 0) {
return 'link-status-icon-red'; return 'link-status-icon-red';
} }
@ -425,7 +423,6 @@ export default memo(withGlobal<OwnProps>(
exportedInvites: invites, exportedInvites: invites,
revokedExportedInvites: revokedInvites, revokedExportedInvites: revokedInvites,
chat, chat,
serverTimeOffset: global.serverTimeOffset,
isChannel, isChannel,
}; };
}, },

View File

@ -27,7 +27,6 @@ type OwnProps = {
type StateProps = { type StateProps = {
chat?: ApiChat; chat?: ApiChat;
isChannel?: boolean; isChannel?: boolean;
serverTimeOffset: number;
}; };
const ManageJoinRequests: FC<OwnProps & StateProps> = ({ const ManageJoinRequests: FC<OwnProps & StateProps> = ({
@ -129,7 +128,6 @@ export default memo(withGlobal<OwnProps>(
return { return {
chat, chat,
serverTimeOffset: global.serverTimeOffset,
isChannel: chat && isChatChannel(chat), isChannel: chat && isChatChannel(chat),
}; };
}, },

View File

@ -200,7 +200,7 @@ addActionHandler('restartBot', async (global, actions, payload) => {
addActionHandler('loadTopInlineBots', async (global) => { addActionHandler('loadTopInlineBots', async (global) => {
const { lastRequestedAt } = global.topInlineBots; const { lastRequestedAt } = global.topInlineBots;
if (lastRequestedAt && getServerTime(global.serverTimeOffset) - lastRequestedAt < TOP_PEERS_REQUEST_COOLDOWN) { if (lastRequestedAt && getServerTime() - lastRequestedAt < TOP_PEERS_REQUEST_COOLDOWN) {
return; return;
} }
@ -218,7 +218,7 @@ addActionHandler('loadTopInlineBots', async (global) => {
topInlineBots: { topInlineBots: {
...global.topInlineBots, ...global.topInlineBots,
userIds: ids, userIds: ids,
lastRequestedAt: getServerTime(global.serverTimeOffset), lastRequestedAt: getServerTime(),
}, },
}; };
setGlobal(global); setGlobal(global);

View File

@ -263,7 +263,6 @@ addActionHandler('loadTopChats', () => {
}); });
addActionHandler('requestChatUpdate', (global, actions, payload) => { addActionHandler('requestChatUpdate', (global, actions, payload) => {
const { serverTimeOffset } = global;
const { chatId } = payload!; const { chatId } = payload!;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
@ -272,7 +271,6 @@ addActionHandler('requestChatUpdate', (global, actions, payload) => {
void callApi('requestChatUpdate', { void callApi('requestChatUpdate', {
chat, chat,
serverTimeOffset,
...(chatId === SERVICE_NOTIFICATIONS_USER_ID && { ...(chatId === SERVICE_NOTIFICATIONS_USER_ID && {
lastLocalMessage: selectLastServiceNotification(global)?.message, lastLocalMessage: selectLastServiceNotification(global)?.message,
}), }),
@ -280,7 +278,6 @@ addActionHandler('requestChatUpdate', (global, actions, payload) => {
}); });
addActionHandler('updateChatMutedState', (global, actions, payload) => { addActionHandler('updateChatMutedState', (global, actions, payload) => {
const { serverTimeOffset } = global;
const { chatId, isMuted } = payload!; const { chatId, isMuted } = payload!;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
@ -288,11 +285,10 @@ addActionHandler('updateChatMutedState', (global, actions, payload) => {
} }
setGlobal(updateChat(global, chatId, { isMuted })); setGlobal(updateChat(global, chatId, { isMuted }));
void callApi('updateChatMutedState', { chat, isMuted, serverTimeOffset }); void callApi('updateChatMutedState', { chat, isMuted });
}); });
addActionHandler('updateTopicMutedState', (global, actions, payload) => { addActionHandler('updateTopicMutedState', (global, actions, payload) => {
const { serverTimeOffset } = global;
const { chatId, isMuted, topicId } = payload; const { chatId, isMuted, topicId } = payload;
const chat = selectChat(global, chatId); const chat = selectChat(global, chatId);
if (!chat) { if (!chat) {
@ -301,7 +297,7 @@ addActionHandler('updateTopicMutedState', (global, actions, payload) => {
setGlobal(updateTopic(global, chatId, topicId, { isMuted })); setGlobal(updateTopic(global, chatId, topicId, { isMuted }));
void callApi('updateTopicMutedState', { void callApi('updateTopicMutedState', {
chat, topicId, isMuted, serverTimeOffset, chat, topicId, isMuted,
}); });
}); });
@ -582,11 +578,10 @@ addActionHandler('deleteChatFolder', (global, actions, payload) => {
addActionHandler('toggleChatUnread', (global, actions, payload) => { addActionHandler('toggleChatUnread', (global, actions, payload) => {
const { id } = payload!; const { id } = payload!;
const { serverTimeOffset } = global;
const chat = selectChat(global, id); const chat = selectChat(global, id);
if (chat) { if (chat) {
if (chat.unreadCount) { if (chat.unreadCount) {
void callApi('markMessageListRead', { serverTimeOffset, chat, threadId: MAIN_THREAD_ID }); void callApi('markMessageListRead', { chat, threadId: MAIN_THREAD_ID });
} else { } else {
void callApi('toggleDialogUnread', { void callApi('toggleDialogUnread', {
chat, chat,
@ -608,7 +603,6 @@ addActionHandler('markTopicRead', (global, actions, payload) => {
chat, chat,
threadId: topicId, threadId: topicId,
maxId: lastTopicMessageId, maxId: lastTopicMessageId,
serverTimeOffset: global.serverTimeOffset,
}); });
global = getGlobal(); global = getGlobal();
@ -1553,7 +1547,6 @@ async function loadChats(
offsetDate, offsetDate,
archived: listType === 'archived', archived: listType === 'archived',
withPinned: shouldReplace, withPinned: shouldReplace,
serverTimeOffset: global.serverTimeOffset,
lastLocalServiceMessage, lastLocalServiceMessage,
}); });

View File

@ -303,7 +303,6 @@ addActionHandler('sendMessage', (global, actions, payload) => {
}); });
addActionHandler('editMessage', (global, actions, payload) => { addActionHandler('editMessage', (global, actions, payload) => {
const { serverTimeOffset } = global;
const { text, entities } = payload!; const { text, entities } = payload!;
const currentMessageList = selectCurrentMessageList(global); const currentMessageList = selectCurrentMessageList(global);
@ -319,7 +318,7 @@ addActionHandler('editMessage', (global, actions, payload) => {
} }
void callApi('editMessage', { void callApi('editMessage', {
chat, message, text, entities, noWebPage: selectNoWebPage(global, chatId, threadId), serverTimeOffset, chat, message, text, entities, noWebPage: selectNoWebPage(global, chatId, threadId),
}); });
actions.setEditingId({ messageId: undefined }); actions.setEditingId({ messageId: undefined });
@ -515,7 +514,6 @@ addActionHandler('sendMessageAction', async (global, actions, payload) => {
}); });
addActionHandler('markMessageListRead', (global, actions, payload) => { addActionHandler('markMessageListRead', (global, actions, payload) => {
const { serverTimeOffset } = global;
const currentMessageList = selectCurrentMessageList(global); const currentMessageList = selectCurrentMessageList(global);
if (!currentMessageList) { if (!currentMessageList) {
return undefined; return undefined;
@ -531,7 +529,7 @@ addActionHandler('markMessageListRead', (global, actions, payload) => {
runDebouncedForMarkRead(() => { runDebouncedForMarkRead(() => {
void callApi('markMessageListRead', { void callApi('markMessageListRead', {
serverTimeOffset, chat, threadId, maxId, chat, threadId, maxId,
}); });
}); });
@ -679,7 +677,6 @@ addActionHandler('forwardMessages', (global, action, payload) => {
toChat, toChat,
toThreadId, toThreadId,
messages: realMessages, messages: realMessages,
serverTimeOffset: getGlobal().serverTimeOffset,
isSilent, isSilent,
scheduledAt, scheduledAt,
sendAs, sendAs,
@ -992,7 +989,6 @@ async function sendMessage(params: {
sticker?: ApiSticker; sticker?: ApiSticker;
gif?: ApiVideo; gif?: ApiVideo;
poll?: ApiNewPoll; poll?: ApiNewPoll;
serverTimeOffset?: number;
isSilent?: boolean; isSilent?: boolean;
scheduledAt?: number; scheduledAt?: number;
sendAs?: ApiChat | ApiUser; sendAs?: ApiChat | ApiUser;
@ -1024,7 +1020,6 @@ async function sendMessage(params: {
} }
const global = getGlobal(); const global = getGlobal();
params.serverTimeOffset = global.serverTimeOffset;
const currentMessageList = selectCurrentMessageList(global); const currentMessageList = selectCurrentMessageList(global);
if (!currentMessageList) { if (!currentMessageList) {
return; return;

View File

@ -316,10 +316,8 @@ addActionHandler('unblockContact', async (global, actions, payload) => {
setGlobal(removeBlockedContact(getGlobal(), contactId)); setGlobal(removeBlockedContact(getGlobal(), contactId));
}); });
addActionHandler('loadNotificationExceptions', async (global) => { addActionHandler('loadNotificationExceptions', async () => {
const { serverTimeOffset } = global; const result = await callApi('fetchNotificationExceptions');
const result = await callApi('fetchNotificationExceptions', { serverTimeOffset });
if (!result) { if (!result) {
return; return;
} }
@ -327,11 +325,8 @@ addActionHandler('loadNotificationExceptions', async (global) => {
setGlobal(addNotifyExceptions(getGlobal(), result)); setGlobal(addNotifyExceptions(getGlobal(), result));
}); });
addActionHandler('loadNotificationSettings', async (global) => { addActionHandler('loadNotificationSettings', async () => {
const { serverTimeOffset } = global; const result = await callApi('fetchNotificationSettings');
const result = await callApi('fetchNotificationSettings', {
serverTimeOffset,
});
if (!result) { if (!result) {
return; return;
} }
@ -637,11 +632,11 @@ addActionHandler('loadAppConfig', async () => {
}); });
}); });
addActionHandler('loadConfig', async (global) => { addActionHandler('loadConfig', async () => {
const config = await callApi('fetchConfig'); const config = await callApi('fetchConfig');
if (!config) return; if (!config) return;
const timeout = config.expiresAt - getServerTime(global.serverTimeOffset); const timeout = config.expiresAt - getServerTime();
requestActionTimeout('loadConfig', timeout * 1000); requestActionTimeout('loadConfig', timeout * 1000);
setGlobal({ setGlobal({

View File

@ -66,7 +66,7 @@ addActionHandler('loadUser', async (global, actions, payload) => {
addActionHandler('loadTopUsers', (global) => { addActionHandler('loadTopUsers', (global) => {
const { topPeers: { lastRequestedAt } } = global; const { topPeers: { lastRequestedAt } } = global;
if (!lastRequestedAt || getServerTime(global.serverTimeOffset) - lastRequestedAt > TOP_PEERS_REQUEST_COOLDOWN) { if (!lastRequestedAt || getServerTime() - lastRequestedAt > TOP_PEERS_REQUEST_COOLDOWN) {
void loadTopUsers(); void loadTopUsers();
} }
}); });
@ -138,7 +138,7 @@ async function loadTopUsers() {
topPeers: { topPeers: {
...global.topPeers, ...global.topPeers,
userIds: ids, userIds: ids,
lastRequestedAt: getServerTime(global.serverTimeOffset), lastRequestedAt: getServerTime(),
}, },
}; };
setGlobal(global); setGlobal(global);

View File

@ -19,6 +19,7 @@ import { selectNotifySettings } from '../../selectors';
import { forceWebsync } from '../../../util/websync'; import { forceWebsync } from '../../../util/websync';
import { getShippingError, shouldClosePaymentModal } from '../../../util/getReadableErrorText'; import { getShippingError, shouldClosePaymentModal } from '../../../util/getReadableErrorText';
import { clearWebTokenAuth } from '../../../util/routing'; import { clearWebTokenAuth } from '../../../util/routing';
import { setServerTimeOffset } from '../../../util/serverTime';
addActionHandler('apiUpdate', (global, actions, update) => { addActionHandler('apiUpdate', (global, actions, update) => {
switch (update['@type']) { switch (update['@type']) {
@ -205,16 +206,7 @@ function onUpdateSession(update: ApiUpdateSession) {
} }
function onUpdateServerTimeOffset(update: ApiUpdateServerTimeOffset) { function onUpdateServerTimeOffset(update: ApiUpdateServerTimeOffset) {
const global = getGlobal(); setServerTimeOffset(update.serverTimeOffset);
if (global.serverTimeOffset === update.serverTimeOffset) {
return;
}
setGlobal({
...global,
serverTimeOffset: update.serverTimeOffset,
});
} }
function onUpdateCurrentUser(update: ApiUpdateCurrentUser) { function onUpdateCurrentUser(update: ApiUpdateCurrentUser) {

View File

@ -645,7 +645,7 @@ addActionHandler('checkVersionNotification', (global, actions) => {
const message: Omit<ApiMessage, 'id'> = { const message: Omit<ApiMessage, 'id'> = {
chatId: SERVICE_NOTIFICATIONS_USER_ID, chatId: SERVICE_NOTIFICATIONS_USER_ID,
date: getServerTime(global.serverTimeOffset), date: getServerTime(),
content: { content: {
text: parseMessageInput(versionNotification, true), text: parseMessageInput(versionNotification, true),
}, },

View File

@ -4,7 +4,7 @@ import { SERVICE_NOTIFICATIONS_USER_ID } from '../../config';
import { formatFullDate, formatTime } from '../../util/dateFormat'; import { formatFullDate, formatTime } from '../../util/dateFormat';
import { orderBy } from '../../util/iteratees'; import { orderBy } from '../../util/iteratees';
import type { LangFn } from '../../hooks/useLang'; import type { LangFn } from '../../hooks/useLang';
import { getServerTime } from '../../util/serverTime'; import { getServerTime, getServerTimeOffset } from '../../util/serverTime';
import { prepareSearchWordsForNeedle } from '../../util/searchWords'; import { prepareSearchWordsForNeedle } from '../../util/searchWords';
import { formatPhoneNumber } from '../../util/phoneNumber'; import { formatPhoneNumber } from '../../util/phoneNumber';
@ -67,7 +67,7 @@ export function getUserFullName(user?: ApiUser) {
} }
export function getUserStatus( export function getUserStatus(
lang: LangFn, user: ApiUser, userStatus: ApiUserStatus | undefined, serverTimeOffset: number, lang: LangFn, user: ApiUser, userStatus: ApiUserStatus | undefined,
) { ) {
if (user.id === SERVICE_NOTIFICATIONS_USER_ID) { if (user.id === SERVICE_NOTIFICATIONS_USER_ID) {
return lang('ServiceNotifications').toLowerCase(); return lang('ServiceNotifications').toLowerCase();
@ -99,6 +99,7 @@ export function getUserStatus(
if (!wasOnline) return lang('LastSeen.Offline'); if (!wasOnline) return lang('LastSeen.Offline');
const serverTimeOffset = getServerTimeOffset();
const now = new Date(new Date().getTime() + serverTimeOffset * 1000); const now = new Date(new Date().getTime() + serverTimeOffset * 1000);
const wasOnlineDate = new Date(wasOnline * 1000); const wasOnlineDate = new Date(wasOnline * 1000);
@ -191,10 +192,9 @@ export function sortUserIds(
usersById: Record<string, ApiUser>, usersById: Record<string, ApiUser>,
userStatusesById: Record<string, ApiUserStatus>, userStatusesById: Record<string, ApiUserStatus>,
priorityIds?: string[], priorityIds?: string[],
serverTimeOffset = 0,
) { ) {
return orderBy(userIds, (id) => { return orderBy(userIds, (id) => {
const now = getServerTime(serverTimeOffset); const now = getServerTime();
if (priorityIds && priorityIds.includes(id)) { if (priorityIds && priorityIds.includes(id)) {
// Assuming that online status expiration date can't be as far as two days from now, // Assuming that online status expiration date can't be as far as two days from now,

View File

@ -14,7 +14,6 @@ export const INITIAL_STATE: GlobalState = {
isChatInfoShown: false, isChatInfoShown: false,
newChatMembersProgress: NewChatMembersProgress.Closed, newChatMembersProgress: NewChatMembersProgress.Closed,
uiReadyState: 0, uiReadyState: 0,
serverTimeOffset: 0,
isUpdateAvailable: false, isUpdateAvailable: false,
authRememberMe: true, authRememberMe: true,

View File

@ -464,7 +464,7 @@ export function selectAllowedMessageActions(global: GlobalState, message: ApiMes
const isMessageEditable = ( const isMessageEditable = (
( (
canEditMessagesIndefinitely canEditMessagesIndefinitely
|| getServerTime(global.serverTimeOffset) - message.date < MESSAGE_EDIT_ALLOWED_TIME || getServerTime() - message.date < MESSAGE_EDIT_ALLOWED_TIME
) && !( ) && !(
content.sticker || content.contact || content.poll || content.action || content.audio content.sticker || content.contact || content.poll || content.action || content.audio
|| (content.video?.isRound) || content.location || content.invoice || (content.video?.isRound) || content.location || content.invoice

View File

@ -159,7 +159,6 @@ export type GlobalState = {
isSyncing?: boolean; isSyncing?: boolean;
isUpdateAvailable?: boolean; isUpdateAvailable?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
serverTimeOffset: number;
leftColumnWidth?: number; leftColumnWidth?: number;
// TODO Move to `auth`. // TODO Move to `auth`.

View File

@ -1,11 +1,11 @@
import React, { useCallback, useState } from '../lib/teact/teact'; import React, { useCallback, useState } from '../lib/teact/teact';
import { getGlobal } from '../lib/teact/teactn';
import { SCHEDULED_WHEN_ONLINE } from '../config'; import { SCHEDULED_WHEN_ONLINE } from '../config';
import { getDayStartAt } from '../util/dateFormat'; import { getDayStartAt } from '../util/dateFormat';
import useLang from './useLang'; import useLang from './useLang';
import CalendarModal from '../components/common/CalendarModal.async'; import CalendarModal from '../components/common/CalendarModal.async';
import { getServerTimeOffset } from '../util/serverTime';
type OnScheduledCallback = (scheduledAt: number) => void; type OnScheduledCallback = (scheduledAt: number) => void;
@ -18,10 +18,9 @@ const useSchedule = (
const [onScheduled, setOnScheduled] = useState<OnScheduledCallback | undefined>(); const [onScheduled, setOnScheduled] = useState<OnScheduledCallback | undefined>();
const handleMessageSchedule = useCallback((date: Date, isWhenOnline = false) => { const handleMessageSchedule = useCallback((date: Date, isWhenOnline = false) => {
const { serverTimeOffset } = getGlobal();
// Scheduled time can not be less than 10 seconds in future // Scheduled time can not be less than 10 seconds in future
const scheduledAt = Math.round(Math.max(date.getTime(), Date.now() + 60 * 1000) / 1000) const scheduledAt = Math.round(Math.max(date.getTime(), Date.now() + 60 * 1000) / 1000)
+ (isWhenOnline ? 0 : serverTimeOffset); + (isWhenOnline ? 0 : getServerTimeOffset());
onScheduled?.(scheduledAt); onScheduled?.(scheduledAt);
setOnScheduled(undefined); setOnScheduled(undefined);
}, [onScheduled]); }, [onScheduled]);

View File

@ -179,12 +179,8 @@ let areSettingsLoaded = false;
async function loadNotificationSettings() { async function loadNotificationSettings() {
if (areSettingsLoaded) return selectNotifySettings(getGlobal()); if (areSettingsLoaded) return selectNotifySettings(getGlobal());
const [resultSettings, resultExceptions] = await Promise.all([ const [resultSettings, resultExceptions] = await Promise.all([
callApi('fetchNotificationSettings', { callApi('fetchNotificationSettings'),
serverTimeOffset: getGlobal().serverTimeOffset, callApi('fetchNotificationExceptions'),
}),
callApi('fetchNotificationExceptions', {
serverTimeOffset: getGlobal().serverTimeOffset,
}),
]); ]);
if (!resultSettings) return selectNotifySettings(getGlobal()); if (!resultSettings) return selectNotifySettings(getGlobal());

View File

@ -1,3 +1,13 @@
export const getServerTime = (serverTimeOffset: number) => { let serverTimeOffset = 0;
export function setServerTimeOffset(_serverTimeOffset: number) {
serverTimeOffset = _serverTimeOffset;
}
export function getServerTimeOffset() {
return serverTimeOffset;
}
export function getServerTime() {
return Math.floor(Date.now() / 1000) + serverTimeOffset; return Math.floor(Date.now() / 1000) + serverTimeOffset;
}; }