From cdebd3b479994611d4bd79d4b81f11f131692549 Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:28:55 +0200 Subject: [PATCH] Localization: New date formatting (#6780) --- src/components/App.tsx | 2 +- src/components/calls/phone/PhoneCall.tsx | 2 +- src/components/common/Audio.tsx | 2 +- src/components/common/CalendarModal.tsx | 2 +- src/components/common/Composer.tsx | 2 +- src/components/common/File.tsx | 2 +- src/components/common/LastMessageMeta.tsx | 2 +- src/components/common/Media.tsx | 2 +- src/components/common/PreviewMedia.tsx | 2 +- src/components/common/SeenByModal.tsx | 2 +- src/components/common/WebLink.tsx | 2 +- .../common/embedded/EmbeddedMessage.tsx | 2 +- src/components/common/gift/GiftMenuItems.tsx | 2 +- .../common/helpers/giftOriginalInfo.tsx | 2 +- .../common/profile/BusinessHours.tsx | 2 +- .../common/profile/UserBirthday.tsx | 2 +- src/components/left/main/LeftMainHeader.tsx | 2 +- src/components/left/search/AudioResults.tsx | 2 +- src/components/left/search/ChatMessage.tsx | 2 +- src/components/left/search/DateSuggest.tsx | 2 +- src/components/left/search/FileResults.tsx | 2 +- src/components/left/search/LeftSearch.tsx | 2 +- src/components/left/search/LinkResults.tsx | 2 +- .../left/settings/SettingsActiveSession.tsx | 2 +- .../left/settings/SettingsActiveSessions.tsx | 2 +- .../left/settings/SettingsActiveWebsites.tsx | 2 +- .../left/settings/SettingsEditProfile.tsx | 2 +- .../left/settings/SettingsGeneral.tsx | 3 - .../left/settings/SettingsPasskeys.tsx | 2 +- src/components/main/premium/GiveawayModal.tsx | 2 +- .../main/premium/PremiumMainModal.tsx | 2 +- src/components/mediaViewer/SeekLine.tsx | 2 +- src/components/mediaViewer/SenderInfo.tsx | 2 +- .../mediaViewer/VideoPlayerControls.tsx | 2 +- .../middle/MessageListAccountInfo.tsx | 2 +- src/components/middle/MessageListContent.tsx | 2 +- src/components/middle/ReactorListModal.tsx | 2 +- .../middle/composer/AttachmentModalItem.tsx | 2 +- .../middle/helpers/groupMessages.ts | 2 +- .../middle/message/ActionMessageText.tsx | 4 +- src/components/middle/message/BaseStory.tsx | 2 +- src/components/middle/message/Giveaway.tsx | 2 +- .../middle/message/InvoiceMediaPreview.tsx | 2 +- .../middle/message/LastEditTimeMenuItem.tsx | 2 +- src/components/middle/message/Location.tsx | 2 +- src/components/middle/message/MessageMeta.tsx | 2 +- .../middle/message/MessagePhoneCall.tsx | 2 +- src/components/middle/message/Poll.tsx | 2 +- .../middle/message/ReadTimeMenuItem.tsx | 2 +- src/components/middle/message/RoundVideo.tsx | 2 +- src/components/middle/message/Video.tsx | 2 +- .../middle/message/actions/Gift.tsx | 2 +- .../middle/message/actions/GiveawayPrize.tsx | 2 +- .../message/actions/StarGiftPurchaseOffer.tsx | 2 +- .../message/actions/SuggestedPostApproval.tsx | 2 +- src/components/middle/search/MiddleSearch.tsx | 2 +- src/components/modals/boost/BoostModal.tsx | 2 +- .../collectible/CollectibleInfoModal.tsx | 2 +- .../frozenAccount/FrozenAccountModal.tsx | 2 +- src/components/modals/gift/GiftComposer.tsx | 2 +- .../gift/StarGiftPriceDecreaseInfoModal.tsx | 2 +- .../modals/gift/UniqueGiftManageButtons.tsx | 2 +- .../gift/auction/GiftAuctionAcquiredModal.tsx | 2 +- .../modals/gift/auction/GiftAuctionModal.tsx | 2 +- .../modals/gift/info/GiftInfoModal.tsx | 2 +- .../modals/gift/locked/GiftLockedModal.tsx | 2 +- .../modals/gift/value/GiftInfoValueModal.tsx | 2 +- .../modals/giftcode/GiftCodeModal.tsx | 2 +- .../profileRating/ProfileRatingModal.tsx | 2 +- .../subscription/StarsSubscriptionItem.tsx | 2 +- .../subscription/StarsSubscriptionModal.tsx | 2 +- .../transaction/StarsTransactionItem.tsx | 2 +- .../transaction/StarsTransactionModal.tsx | 2 +- .../suggestMessage/SuggestMessageModal.tsx | 2 +- .../SuggestedPostApprovalModal.tsx | 2 +- .../suggestedStatus/SuggestedStatusModal.tsx | 2 +- src/components/right/PollAnswerResults.tsx | 2 +- .../right/management/JoinRequest.tsx | 2 +- .../right/management/ManageInvite.tsx | 2 +- .../right/management/ManageInviteInfo.tsx | 2 +- .../right/management/ManageInvites.tsx | 2 +- .../right/statistics/BoostStatistics.tsx | 2 +- .../right/statistics/StatisticsOverview.tsx | 2 +- .../statistics/StatisticsRecentMessage.tsx | 2 +- .../statistics/StatisticsRecentStory.tsx | 2 +- src/components/story/MediaStory.tsx | 2 +- src/components/story/Story.tsx | 2 +- src/components/story/StoryRibbonButton.tsx | 2 +- src/components/story/StoryView.tsx | 2 +- .../test/TestDateFormat.module.scss | 29 ++ src/components/test/TestDateFormat.tsx | 128 +++++++ src/components/test/TestDateFormatPerf.tsx | 317 ++++++++++++++++++ src/components/ui/RoundTimer.tsx | 2 +- src/components/ui/TextTimer.tsx | 2 +- src/config.ts | 3 +- src/global/actions/api/globalSearch.ts | 2 +- src/global/actions/api/settings.ts | 3 - src/global/actions/ui/initial.ts | 6 +- src/global/actions/ui/settings.ts | 6 +- src/global/helpers/chats.ts | 2 +- src/global/helpers/users.ts | 2 +- src/hooks/useSchedule.tsx | 2 +- src/util/data/readFallbackStrings.ts | 4 +- .../dates/{dateFormat.ts => oldDateFormat.ts} | 0 src/util/formatCurrency.tsx | 4 +- src/util/localization/dateFormat.ts | 248 ++++++++++++++ src/util/localization/index.ts | 42 ++- src/util/localization/types.ts | 2 + src/util/oldLangProvider.ts | 3 +- 109 files changed, 869 insertions(+), 119 deletions(-) create mode 100644 src/components/test/TestDateFormat.module.scss create mode 100644 src/components/test/TestDateFormat.tsx create mode 100644 src/components/test/TestDateFormatPerf.tsx rename src/util/dates/{dateFormat.ts => oldDateFormat.ts} (100%) create mode 100644 src/util/localization/dateFormat.ts diff --git a/src/components/App.tsx b/src/components/App.tsx index ff8d7dd16..dbbb1340a 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -24,13 +24,13 @@ import usePrevious from '../hooks/usePrevious'; import { useSignalEffect } from '../hooks/useSignalEffect'; import { getIsInBackground } from '../hooks/window/useBackgroundMode'; -// import Test from './test/TestCleanupOrder'; import Auth from './auth/Auth'; import Notifications from './common/Notifications'; import UiLoader from './common/UiLoader'; import AppInactive from './main/AppInactive'; import LockScreen from './main/LockScreen.async'; import Main from './main/Main.async'; +// import Test from './test/TestDateFormat'; import Transition from './ui/Transition'; import styles from './App.module.scss'; diff --git a/src/components/calls/phone/PhoneCall.tsx b/src/components/calls/phone/PhoneCall.tsx index 56e6153f3..8281c1cb4 100644 --- a/src/components/calls/phone/PhoneCall.tsx +++ b/src/components/calls/phone/PhoneCall.tsx @@ -18,7 +18,7 @@ import { IS_REQUEST_FULLSCREEN_SUPPORTED, } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets'; import renderText from '../../common/helpers/renderText'; diff --git a/src/components/common/Audio.tsx b/src/components/common/Audio.tsx index 1a3f7d290..5781e5f0b 100644 --- a/src/components/common/Audio.tsx +++ b/src/components/common/Audio.tsx @@ -29,7 +29,7 @@ import { selectMessageMediaDuration } from '../../global/selectors/media'; import { makeTrackId } from '../../util/audioPlayer'; import buildClassName from '../../util/buildClassName'; import { captureEvents } from '../../util/captureEvents'; -import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dates/dateFormat'; +import { formatMediaDateTime, formatMediaDuration, formatPastTimeShort } from '../../util/dates/oldDateFormat'; import { decodeWaveform, interpolateArray } from '../../util/waveform'; import { LOCAL_TGS_URLS } from './helpers/animatedAssets'; import renderText from './helpers/renderText'; diff --git a/src/components/common/CalendarModal.tsx b/src/components/common/CalendarModal.tsx index 2f7affb3a..9c0a5814b 100644 --- a/src/components/common/CalendarModal.tsx +++ b/src/components/common/CalendarModal.tsx @@ -11,7 +11,7 @@ import type { RepeatedMessageMode } from '../../util/scheduledMessages'; import { MAX_INT_32 } from '../../config'; import { selectIsCurrentUserPremium } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatDateToString, formatTime, getDayStart } from '../../util/dates/dateFormat'; +import { formatDateToString, formatTime, getDayStart } from '../../util/dates/oldDateFormat'; import { ALL_REPEAT_MODES, getScheduleRepeatModeText, TEST_SERVER_ONLY_MODES } from '../../util/scheduledMessages'; import useContextMenuHandlers from '../../hooks/useContextMenuHandlers'; diff --git a/src/components/common/Composer.tsx b/src/components/common/Composer.tsx index 6f3907a3c..b5b0ffc38 100644 --- a/src/components/common/Composer.tsx +++ b/src/components/common/Composer.tsx @@ -115,7 +115,7 @@ import { } from '../../global/selectors/threads'; import { IS_IOS, IS_VOICE_RECORDING_SUPPORTED } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration, formatVoiceRecordDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration, formatVoiceRecordDuration } from '../../util/dates/oldDateFormat'; import { processDeepLink } from '../../util/deeplink'; import { tryParseDeepLink } from '../../util/deepLinkParser'; import deleteLastCharacterOutsideSelection from '../../util/deleteLastCharacterOutsideSelection'; diff --git a/src/components/common/File.tsx b/src/components/common/File.tsx index c5456f57e..6e584b26d 100644 --- a/src/components/common/File.tsx +++ b/src/components/common/File.tsx @@ -7,7 +7,7 @@ import type { IconName } from '../../types/icons'; import { IS_CANVAS_FILTER_SUPPORTED } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDateTime, formatPastTimeShort } from '../../util/dates/dateFormat'; +import { formatMediaDateTime, formatPastTimeShort } from '../../util/dates/oldDateFormat'; import { getColorFromExtension } from './helpers/documentInfo'; import { getDocumentThumbnailDimensions } from './helpers/mediaDimensions'; import renderText from './helpers/renderText'; diff --git a/src/components/common/LastMessageMeta.tsx b/src/components/common/LastMessageMeta.tsx index be98ca70c..870aa06e6 100644 --- a/src/components/common/LastMessageMeta.tsx +++ b/src/components/common/LastMessageMeta.tsx @@ -3,7 +3,7 @@ import { memo } from '../../lib/teact/teact'; import type { ApiMessage, ApiMessageOutgoingStatus } from '../../api/types'; import buildClassName from '../../util/buildClassName'; -import { formatPastTimeShort } from '../../util/dates/dateFormat'; +import { formatPastTimeShort } from '../../util/dates/oldDateFormat'; import useOldLang from '../../hooks/useOldLang'; diff --git a/src/components/common/Media.tsx b/src/components/common/Media.tsx index 6d56b30d9..a706c477f 100644 --- a/src/components/common/Media.tsx +++ b/src/components/common/Media.tsx @@ -11,7 +11,7 @@ import { } from '../../global/helpers'; import { IS_TOUCH_ENV } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import stopEvent from '../../util/stopEvent'; import useMessageMediaHash from '../../hooks/media/useMessageMediaHash'; diff --git a/src/components/common/PreviewMedia.tsx b/src/components/common/PreviewMedia.tsx index 3fdd2f9c2..bd7fee06c 100644 --- a/src/components/common/PreviewMedia.tsx +++ b/src/components/common/PreviewMedia.tsx @@ -5,7 +5,7 @@ import type { ApiBotPreviewMedia } from '../../api/types'; import type { ObserveFn } from '../../hooks/useIntersectionObserver'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import stopEvent from '../../util/stopEvent'; import useMessageMediaHash from '../../hooks/media/useMessageMediaHash'; diff --git a/src/components/common/SeenByModal.tsx b/src/components/common/SeenByModal.tsx index 4790883fe..8f153e87c 100644 --- a/src/components/common/SeenByModal.tsx +++ b/src/components/common/SeenByModal.tsx @@ -3,7 +3,7 @@ import { getActions, withGlobal } from '../../global'; import { selectChatMessage, selectTabState } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatDateAtTime } from '../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../util/dates/oldDateFormat'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useLastCallback from '../../hooks/useLastCallback'; diff --git a/src/components/common/WebLink.tsx b/src/components/common/WebLink.tsx index 8880dac4c..0f23a6c66 100644 --- a/src/components/common/WebLink.tsx +++ b/src/components/common/WebLink.tsx @@ -11,7 +11,7 @@ import { } from '../../global/helpers'; import { selectWebPageFromMessage } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatPastTimeShort } from '../../util/dates/dateFormat'; +import { formatPastTimeShort } from '../../util/dates/oldDateFormat'; import trimText from '../../util/trimText'; import { renderMessageSummary } from './helpers/renderMessageText'; import renderText from './helpers/renderText'; diff --git a/src/components/common/embedded/EmbeddedMessage.tsx b/src/components/common/embedded/EmbeddedMessage.tsx index 4a9eea144..412635d40 100644 --- a/src/components/common/embedded/EmbeddedMessage.tsx +++ b/src/components/common/embedded/EmbeddedMessage.tsx @@ -20,7 +20,7 @@ import { import { getMediaContentTypeDescription } from '../../../global/helpers/messageSummary'; import { getPeerTitle } from '../../../global/helpers/peers'; import buildClassName from '../../../util/buildClassName'; -import { formatScheduledDateTime } from '../../../util/dates/dateFormat'; +import { formatScheduledDateTime } from '../../../util/dates/oldDateFormat'; import { isUserId } from '../../../util/entities/ids'; import { formatStarsAsIcon, formatTonAsIcon } from '../../../util/localization/format'; import { getPictogramDimensions } from '../helpers/mediaDimensions'; diff --git a/src/components/common/gift/GiftMenuItems.tsx b/src/components/common/gift/GiftMenuItems.tsx index 46b8081c6..bfc6a59ca 100644 --- a/src/components/common/gift/GiftMenuItems.tsx +++ b/src/components/common/gift/GiftMenuItems.tsx @@ -8,7 +8,7 @@ import type { import { DEFAULT_STATUS_ICON_ID, TME_LINK_PREFIX } from '../../../config'; import { STARS_CURRENCY_CODE } from '../../../config'; import { copyTextToClipboard } from '../../../util/clipboard'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import useLang from '../../../hooks/useLang'; diff --git a/src/components/common/helpers/giftOriginalInfo.tsx b/src/components/common/helpers/giftOriginalInfo.tsx index 184ac60a9..5ab5cdc9e 100644 --- a/src/components/common/helpers/giftOriginalInfo.tsx +++ b/src/components/common/helpers/giftOriginalInfo.tsx @@ -3,7 +3,7 @@ import type { TeactNode } from '../../../lib/teact/teact'; import type { ApiPeer, ApiStarGiftAttributeOriginalDetails } from '../../../api/types'; import { getPeerTitle } from '../../../global/helpers/peers'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import { type LangFn } from '../../../util/localization'; import { renderTextWithEntities } from './renderTextWithEntities'; diff --git a/src/components/common/profile/BusinessHours.tsx b/src/components/common/profile/BusinessHours.tsx index 13cab6285..e453f3bd3 100644 --- a/src/components/common/profile/BusinessHours.tsx +++ b/src/components/common/profile/BusinessHours.tsx @@ -12,7 +12,7 @@ import { } from '../../../util/animations/viewTransitionTypes'; import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatTime, formatWeekday } from '../../../util/dates/dateFormat'; +import { formatTime, formatWeekday } from '../../../util/dates/oldDateFormat'; import { getUtcOffset, getWeekStart, shiftTimeRanges, splitDays, } from '../../../util/dates/workHours'; diff --git a/src/components/common/profile/UserBirthday.tsx b/src/components/common/profile/UserBirthday.tsx index 7be5298be..4900adaa8 100644 --- a/src/components/common/profile/UserBirthday.tsx +++ b/src/components/common/profile/UserBirthday.tsx @@ -12,7 +12,7 @@ import { getStickerMediaHash } from '../../../global/helpers'; import { selectIsPremiumPurchaseBlocked } from '../../../global/selectors'; import { IS_OFFSET_PATH_SUPPORTED } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatDateToString } from '../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../util/dates/oldDateFormat'; import { buildCollectionByKey } from '../../../util/iteratees'; import * as mediaLoader from '../../../util/mediaLoader'; import renderText from '../helpers/renderText'; diff --git a/src/components/left/main/LeftMainHeader.tsx b/src/components/left/main/LeftMainHeader.tsx index 38e5203e9..d48e88cc2 100644 --- a/src/components/left/main/LeftMainHeader.tsx +++ b/src/components/left/main/LeftMainHeader.tsx @@ -21,7 +21,7 @@ import { IS_TAURI } from '../../../util/browser/globalEnvironment'; import { IS_APP, IS_MAC_OS } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; import captureEscKeyListener from '../../../util/captureEscKeyListener'; -import { formatDateToString } from '../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../util/dates/oldDateFormat'; import useAppLayout from '../../../hooks/useAppLayout'; import useConnectionStatus from '../../../hooks/useConnectionStatus'; diff --git a/src/components/left/search/AudioResults.tsx b/src/components/left/search/AudioResults.tsx index 3dbee6ab4..3e7bee325 100644 --- a/src/components/left/search/AudioResults.tsx +++ b/src/components/left/search/AudioResults.tsx @@ -9,7 +9,7 @@ import { AudioOrigin, LoadMoreDirection } from '../../../types'; import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { getIsDownloading } from '../../../global/helpers'; import { selectMessageDownloadableMedia } from '../../../global/selectors/media'; -import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat'; +import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat'; import { parseSearchResultKey } from '../../../util/keys/searchResultKey'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { throttle } from '../../../util/schedulers'; diff --git a/src/components/left/search/ChatMessage.tsx b/src/components/left/search/ChatMessage.tsx index e72ffef30..3ade03691 100644 --- a/src/components/left/search/ChatMessage.tsx +++ b/src/components/left/search/ChatMessage.tsx @@ -15,7 +15,7 @@ import { import { isApiPeerUser } from '../../../global/helpers/peers'; import { selectPeer } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatPastTimeShort } from '../../../util/dates/dateFormat'; +import { formatPastTimeShort } from '../../../util/dates/oldDateFormat'; import { type LangFn } from '../../../util/localization'; import { renderMessageSummary } from '../../common/helpers/renderMessageText'; diff --git a/src/components/left/search/DateSuggest.tsx b/src/components/left/search/DateSuggest.tsx index 1c6d413b0..7b78a2edc 100644 --- a/src/components/left/search/DateSuggest.tsx +++ b/src/components/left/search/DateSuggest.tsx @@ -1,7 +1,7 @@ import type { FC } from '../../../lib/teact/teact'; import { memo, useMemo } from '../../../lib/teact/teact'; -import { formatDateToString } from '../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../util/dates/oldDateFormat'; import Icon from '../../common/icons/Icon'; diff --git a/src/components/left/search/FileResults.tsx b/src/components/left/search/FileResults.tsx index 1ece9064c..2e6a09f31 100644 --- a/src/components/left/search/FileResults.tsx +++ b/src/components/left/search/FileResults.tsx @@ -10,7 +10,7 @@ import { LoadMoreDirection } from '../../../types'; import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { getIsDownloading, getMessageDocument } from '../../../global/helpers'; -import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat'; +import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat'; import { parseSearchResultKey } from '../../../util/keys/searchResultKey'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { throttle } from '../../../util/schedulers'; diff --git a/src/components/left/search/LeftSearch.tsx b/src/components/left/search/LeftSearch.tsx index 5eb3cc033..76d30e7c2 100644 --- a/src/components/left/search/LeftSearch.tsx +++ b/src/components/left/search/LeftSearch.tsx @@ -13,7 +13,7 @@ import { type AnimationLevel, GlobalSearchContent } from '../../../types'; import { selectTabState } from '../../../global/selectors'; import { selectSharedSettings } from '../../../global/selectors/sharedState'; -import { parseDateString } from '../../../util/dates/dateFormat'; +import { parseDateString } from '../../../util/dates/oldDateFormat'; import { resolveTransitionName } from '../../../util/resolveTransitionName'; import useHistoryBack from '../../../hooks/useHistoryBack'; diff --git a/src/components/left/search/LinkResults.tsx b/src/components/left/search/LinkResults.tsx index 9b9e709ab..bee9007cf 100644 --- a/src/components/left/search/LinkResults.tsx +++ b/src/components/left/search/LinkResults.tsx @@ -9,7 +9,7 @@ import type { StateProps } from './helpers/createMapStateToProps'; import { LoadMoreDirection } from '../../../types'; import { SLIDE_TRANSITION_DURATION } from '../../../config'; -import { formatMonthAndYear, toYearMonth } from '../../../util/dates/dateFormat'; +import { formatMonthAndYear, toYearMonth } from '../../../util/dates/oldDateFormat'; import { parseSearchResultKey } from '../../../util/keys/searchResultKey'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { throttle } from '../../../util/schedulers'; diff --git a/src/components/left/settings/SettingsActiveSession.tsx b/src/components/left/settings/SettingsActiveSession.tsx index 5173f7ebc..fa5a40932 100644 --- a/src/components/left/settings/SettingsActiveSession.tsx +++ b/src/components/left/settings/SettingsActiveSession.tsx @@ -5,7 +5,7 @@ import { getActions, withGlobal } from '../../../global'; import type { ApiSession } from '../../../api/types'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import getSessionIcon from './helpers/getSessionIcon'; import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; diff --git a/src/components/left/settings/SettingsActiveSessions.tsx b/src/components/left/settings/SettingsActiveSessions.tsx index 978b80eaf..dd95aacbc 100644 --- a/src/components/left/settings/SettingsActiveSessions.tsx +++ b/src/components/left/settings/SettingsActiveSessions.tsx @@ -7,7 +7,7 @@ import { getActions, withGlobal } from '../../../global'; import type { ApiSession } from '../../../api/types'; import type { GlobalState } from '../../../global/types'; -import { formatPastTimeShort } from '../../../util/dates/dateFormat'; +import { formatPastTimeShort } from '../../../util/dates/oldDateFormat'; import getSessionIcon from './helpers/getSessionIcon'; import useFlag from '../../../hooks/useFlag'; diff --git a/src/components/left/settings/SettingsActiveWebsites.tsx b/src/components/left/settings/SettingsActiveWebsites.tsx index d64641f22..81e321d70 100644 --- a/src/components/left/settings/SettingsActiveWebsites.tsx +++ b/src/components/left/settings/SettingsActiveWebsites.tsx @@ -7,7 +7,7 @@ import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiWebSession } from '../../../api/types'; import buildClassName from '../../../util/buildClassName'; -import { formatPastTimeShort } from '../../../util/dates/dateFormat'; +import { formatPastTimeShort } from '../../../util/dates/oldDateFormat'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; diff --git a/src/components/left/settings/SettingsEditProfile.tsx b/src/components/left/settings/SettingsEditProfile.tsx index fa5f8c9a3..118a00b97 100644 --- a/src/components/left/settings/SettingsEditProfile.tsx +++ b/src/components/left/settings/SettingsEditProfile.tsx @@ -11,7 +11,7 @@ import { PURCHASE_USERNAME, TME_LINK_PREFIX, USERNAME_PURCHASE_ERROR } from '../ import { getChatAvatarHash } from '../../../global/helpers'; import { selectTabState, selectUser, selectUserFullInfo } from '../../../global/selectors'; import { selectCurrentLimit } from '../../../global/selectors/limits'; -import { formatDateToString } from '../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../util/dates/oldDateFormat'; import { getNextArrowReplacement } from '../../../util/localization/format'; import { throttle } from '../../../util/schedulers'; import renderText from '../../common/helpers/renderText'; diff --git a/src/components/left/settings/SettingsGeneral.tsx b/src/components/left/settings/SettingsGeneral.tsx index 00f5615b5..59cb00a39 100644 --- a/src/components/left/settings/SettingsGeneral.tsx +++ b/src/components/left/settings/SettingsGeneral.tsx @@ -13,7 +13,6 @@ import { selectSharedSettings } from '../../../global/selectors/sharedState'; import { IS_ANDROID, IS_IOS, IS_MAC_OS, } from '../../../util/browser/windowEnvironment'; -import { setTimeFormat } from '../../../util/oldLangProvider'; import { getSystemTheme } from '../../../util/systemTheme'; import useAppLayout from '../../../hooks/useAppLayout'; @@ -105,8 +104,6 @@ const SettingsGeneral: FC = ({ const handleTimeFormatChange = useCallback((newTimeFormat: string) => { setSharedSettingOption({ timeFormat: newTimeFormat as TimeFormat }); setSharedSettingOption({ wasTimeFormatSetManually: true }); - - setTimeFormat(newTimeFormat as TimeFormat); }, []); const handleMessageSendComboChange = useCallback((newCombo: string) => { diff --git a/src/components/left/settings/SettingsPasskeys.tsx b/src/components/left/settings/SettingsPasskeys.tsx index 9ee6b1d8c..b0734a796 100644 --- a/src/components/left/settings/SettingsPasskeys.tsx +++ b/src/components/left/settings/SettingsPasskeys.tsx @@ -9,7 +9,7 @@ import type { ApiPasskey } from '../../../api/types'; import { IS_WEBAUTHN_SUPPORTED } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatPastDatetime } from '../../../util/dates/dateFormat'; +import { formatPastDatetime } from '../../../util/dates/oldDateFormat'; import { getNextArrowReplacement } from '../../../util/localization/format'; import { LOCAL_TGS_PREVIEW_URLS, LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets'; import { REM } from '../../common/helpers/mediaDimensions'; diff --git a/src/components/main/premium/GiveawayModal.tsx b/src/components/main/premium/GiveawayModal.tsx index 7c21a6852..f01962e8d 100644 --- a/src/components/main/premium/GiveawayModal.tsx +++ b/src/components/main/premium/GiveawayModal.tsx @@ -28,7 +28,7 @@ import { selectTabState, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import { unique } from '../../../util/iteratees'; import renderText from '../../common/helpers/renderText'; diff --git a/src/components/main/premium/PremiumMainModal.tsx b/src/components/main/premium/PremiumMainModal.tsx index 3e810f06b..094aeaa97 100644 --- a/src/components/main/premium/PremiumMainModal.tsx +++ b/src/components/main/premium/PremiumMainModal.tsx @@ -25,7 +25,7 @@ import { } from '../../../global/selectors'; import { selectPremiumLimit } from '../../../global/selectors/limits'; import buildClassName from '../../../util/buildClassName'; -import { formatCountdownDays } from '../../../util/dates/dateFormat'; +import { formatCountdownDays } from '../../../util/dates/oldDateFormat'; import { formatCurrency } from '../../../util/formatCurrency'; import { getStickerFromGift } from '../../common/helpers/gifts'; import { REM } from '../../common/helpers/mediaDimensions'; diff --git a/src/components/mediaViewer/SeekLine.tsx b/src/components/mediaViewer/SeekLine.tsx index c4cfd35d0..5d3b273b9 100644 --- a/src/components/mediaViewer/SeekLine.tsx +++ b/src/components/mediaViewer/SeekLine.tsx @@ -15,7 +15,7 @@ import { IS_TOUCH_ENV } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; import buildStyle from '../../util/buildStyle'; import { captureEvents } from '../../util/captureEvents'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import getPointerPosition from '../../util/events/getPointerPosition'; import { clamp, round } from '../../util/math'; import StoryboardParser from '../../util/media/StoryboardParser'; diff --git a/src/components/mediaViewer/SenderInfo.tsx b/src/components/mediaViewer/SenderInfo.tsx index 55dd4770b..40ed1173f 100644 --- a/src/components/mediaViewer/SenderInfo.tsx +++ b/src/components/mediaViewer/SenderInfo.tsx @@ -12,7 +12,7 @@ import { getPeerTitle } from '../../global/helpers/peers'; import { selectSender, } from '../../global/selectors'; -import { formatMediaDateTime } from '../../util/dates/dateFormat'; +import { formatMediaDateTime } from '../../util/dates/oldDateFormat'; import { isUserId } from '../../util/entities/ids'; import renderText from '../common/helpers/renderText'; diff --git a/src/components/mediaViewer/VideoPlayerControls.tsx b/src/components/mediaViewer/VideoPlayerControls.tsx index 5d12e727d..c55d40e25 100644 --- a/src/components/mediaViewer/VideoPlayerControls.tsx +++ b/src/components/mediaViewer/VideoPlayerControls.tsx @@ -13,7 +13,7 @@ import type { IconName } from '../../types/icons'; import { IS_IOS, IS_TOUCH_ENV } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import useAppLayout from '../../hooks/useAppLayout'; import useCurrentTimeSignal from '../../hooks/useCurrentTimeSignal'; diff --git a/src/components/middle/MessageListAccountInfo.tsx b/src/components/middle/MessageListAccountInfo.tsx index 7087bf780..e0955730c 100644 --- a/src/components/middle/MessageListAccountInfo.tsx +++ b/src/components/middle/MessageListAccountInfo.tsx @@ -24,7 +24,7 @@ import { } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; import buildStyle from '../../util/buildStyle'; -import { formatPastDatetime, formatRegistrationMonth } from '../../util/dates/dateFormat'; +import { formatPastDatetime, formatRegistrationMonth } from '../../util/dates/oldDateFormat'; import { isoToEmoji } from '../../util/emoji/emoji'; import { getCountryCodeByIso } from '../../util/phoneNumber'; import stopEvent from '../../util/stopEvent'; diff --git a/src/components/middle/MessageListContent.tsx b/src/components/middle/MessageListContent.tsx index 612658b55..89a6ebfd2 100644 --- a/src/components/middle/MessageListContent.tsx +++ b/src/components/middle/MessageListContent.tsx @@ -22,7 +22,7 @@ import { import { getPeerTitle } from '../../global/helpers/peers'; import { selectChatMessage, selectSender } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatHumanDate, formatScheduledDateTime } from '../../util/dates/dateFormat'; +import { formatHumanDate, formatScheduledDateTime } from '../../util/dates/oldDateFormat'; import { convertTonFromNanos } from '../../util/formatCurrency'; import { compact } from '../../util/iteratees'; import { formatStarsAsText, formatTonAsText } from '../../util/localization/format'; diff --git a/src/components/middle/ReactorListModal.tsx b/src/components/middle/ReactorListModal.tsx index aeeded8ea..0bee877cd 100644 --- a/src/components/middle/ReactorListModal.tsx +++ b/src/components/middle/ReactorListModal.tsx @@ -17,7 +17,7 @@ import { } from '../../global/selectors'; import { selectSharedSettings } from '../../global/selectors/sharedState'; import buildClassName from '../../util/buildClassName'; -import { formatDateAtTime } from '../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../util/dates/oldDateFormat'; import { unique } from '../../util/iteratees'; import { resolveTransitionName } from '../../util/resolveTransitionName'; import { formatIntegerCompact } from '../../util/textFormat'; diff --git a/src/components/middle/composer/AttachmentModalItem.tsx b/src/components/middle/composer/AttachmentModalItem.tsx index 6e5ff6798..aa2bc41c4 100644 --- a/src/components/middle/composer/AttachmentModalItem.tsx +++ b/src/components/middle/composer/AttachmentModalItem.tsx @@ -4,7 +4,7 @@ import type { ApiAttachment } from '../../../api/types'; import { SUPPORTED_PHOTO_CONTENT_TYPES, SUPPORTED_VIDEO_CONTENT_TYPES } from '../../../config'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import { getFileExtension } from '../../common/helpers/documentInfo'; import { REM } from '../../common/helpers/mediaDimensions'; diff --git a/src/components/middle/helpers/groupMessages.ts b/src/components/middle/helpers/groupMessages.ts index f016843ff..701127a8c 100644 --- a/src/components/middle/helpers/groupMessages.ts +++ b/src/components/middle/helpers/groupMessages.ts @@ -2,7 +2,7 @@ import type { ApiMessage } from '../../../api/types'; import type { IAlbum } from '../../../types'; import { isActionMessage } from '../../../global/helpers'; -import { getDayStartAt } from '../../../util/dates/dateFormat'; +import { getDayStartAt } from '../../../util/dates/oldDateFormat'; type SenderGroup = (ApiMessage | IAlbum)[]; diff --git a/src/components/middle/message/ActionMessageText.tsx b/src/components/middle/message/ActionMessageText.tsx index 847a36bab..b2ea1cfd5 100644 --- a/src/components/middle/message/ActionMessageText.tsx +++ b/src/components/middle/message/ActionMessageText.tsx @@ -27,7 +27,9 @@ import { } from '../../../global/selectors'; import { selectThreadIdFromMessage } from '../../../global/selectors/threads'; import { ensureProtocol } from '../../../util/browser/url'; -import { formatDateTimeToString, formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat'; +import { + formatDateTimeToString, formatScheduledDateTime, formatShortDuration, +} from '../../../util/dates/oldDateFormat'; import { formatCurrency } from '../../../util/formatCurrency'; import { convertTonFromNanos } from '../../../util/formatCurrency'; import { formatCurrencyAmountAsText, formatStarsAsText, formatTonAsText } from '../../../util/localization/format'; diff --git a/src/components/middle/message/BaseStory.tsx b/src/components/middle/message/BaseStory.tsx index 352fed4ac..29a13378e 100644 --- a/src/components/middle/message/BaseStory.tsx +++ b/src/components/middle/message/BaseStory.tsx @@ -6,7 +6,7 @@ import type { ApiMessageStoryData, ApiTypeStory } from '../../../api/types'; import { getStoryMediaHash } from '../../../global/helpers'; import { IS_CANVAS_FILTER_SUPPORTED } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import useAppLayout from '../../../hooks/useAppLayout'; import useCanvasBlur from '../../../hooks/useCanvasBlur'; diff --git a/src/components/middle/message/Giveaway.tsx b/src/components/middle/message/Giveaway.tsx index 38acf9be8..fff649a05 100644 --- a/src/components/middle/message/Giveaway.tsx +++ b/src/components/middle/message/Giveaway.tsx @@ -18,7 +18,7 @@ import { selectGiftStickerForDuration, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatDateAtTime, formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateAtTime, formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import { isoToEmoji } from '../../../util/emoji/emoji'; import { getServerTime } from '../../../util/serverTime'; import { callApi } from '../../../api/gramjs'; diff --git a/src/components/middle/message/InvoiceMediaPreview.tsx b/src/components/middle/message/InvoiceMediaPreview.tsx index fe30157bd..9ca06d41b 100644 --- a/src/components/middle/message/InvoiceMediaPreview.tsx +++ b/src/components/middle/message/InvoiceMediaPreview.tsx @@ -6,7 +6,7 @@ import type { ApiMessage } from '../../../api/types'; import { getMessageInvoice } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import { formatCurrencyAsString } from '../../../util/formatCurrency'; import useInterval from '../../../hooks/schedulers/useInterval'; diff --git a/src/components/middle/message/LastEditTimeMenuItem.tsx b/src/components/middle/message/LastEditTimeMenuItem.tsx index ef16382b4..d3b696e5b 100644 --- a/src/components/middle/message/LastEditTimeMenuItem.tsx +++ b/src/components/middle/message/LastEditTimeMenuItem.tsx @@ -2,7 +2,7 @@ import { memo } from '../../../lib/teact/teact'; import type { ApiMessage } from '../../../api/types'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import useOldLang from '../../../hooks/useOldLang'; diff --git a/src/components/middle/message/Location.tsx b/src/components/middle/message/Location.tsx index fe773ec09..a7ac8999f 100644 --- a/src/components/middle/message/Location.tsx +++ b/src/components/middle/message/Location.tsx @@ -14,7 +14,7 @@ import { isGeoLiveExpired, } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; -import { formatCountdownShort, formatLocationLastUpdate } from '../../../util/dates/dateFormat'; +import { formatCountdownShort, formatLocationLastUpdate } from '../../../util/dates/oldDateFormat'; import { getMetersPerPixel, getVenueColor, getVenueIconUrl, } from '../../../util/map'; diff --git a/src/components/middle/message/MessageMeta.tsx b/src/components/middle/message/MessageMeta.tsx index 0ac8d99bb..205607bc3 100644 --- a/src/components/middle/message/MessageMeta.tsx +++ b/src/components/middle/message/MessageMeta.tsx @@ -8,7 +8,7 @@ import type { } from '../../../api/types'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString, formatPastTimeShort, formatTime } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString, formatPastTimeShort, formatTime } from '../../../util/dates/oldDateFormat'; import { formatStarsAsIcon } from '../../../util/localization/format'; import { getRepeatPeriodText } from '../../../util/scheduledMessages'; import { formatIntegerCompact } from '../../../util/textFormat'; diff --git a/src/components/middle/message/MessagePhoneCall.tsx b/src/components/middle/message/MessagePhoneCall.tsx index 2510ac640..d1bfb6137 100644 --- a/src/components/middle/message/MessagePhoneCall.tsx +++ b/src/components/middle/message/MessagePhoneCall.tsx @@ -7,7 +7,7 @@ import type { ApiMessageActionPhoneCall } from '../../../api/types/messageAction import { ARE_CALLS_SUPPORTED } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; -import { formatTime, formatTimeDuration } from '../../../util/dates/dateFormat'; +import { formatTime, formatTimeDuration } from '../../../util/dates/oldDateFormat'; import { getCallMessageKey } from './helpers/messageActions'; import useLastCallback from '../../../hooks/useLastCallback'; diff --git a/src/components/middle/message/Poll.tsx b/src/components/middle/message/Poll.tsx index 84869e58a..8e83efdeb 100644 --- a/src/components/middle/message/Poll.tsx +++ b/src/components/middle/message/Poll.tsx @@ -17,7 +17,7 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver'; import type { OldLangFn } from '../../../hooks/useOldLang'; import { selectPeer } from '../../../global/selectors'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import { getMessageKey } from '../../../util/keys/messageKey'; import { getServerTime } from '../../../util/serverTime'; import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities'; diff --git a/src/components/middle/message/ReadTimeMenuItem.tsx b/src/components/middle/message/ReadTimeMenuItem.tsx index f5e73a7c3..c881dc32d 100644 --- a/src/components/middle/message/ReadTimeMenuItem.tsx +++ b/src/components/middle/message/ReadTimeMenuItem.tsx @@ -3,7 +3,7 @@ import { getActions } from '../../../global'; import type { ApiMessage } from '../../../api/types'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import useOldLang from '../../../hooks/useOldLang'; diff --git a/src/components/middle/message/RoundVideo.tsx b/src/components/middle/message/RoundVideo.tsx index e50304cf2..a75bc74f8 100644 --- a/src/components/middle/message/RoundVideo.tsx +++ b/src/components/middle/message/RoundVideo.tsx @@ -17,7 +17,7 @@ import { } from '../../../global/helpers'; import { stopCurrentAudio } from '../../../util/audioPlayer'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import safePlay from '../../../util/safePlay'; import { ROUND_VIDEO_DIMENSIONS_PX } from '../../common/helpers/mediaDimensions'; diff --git a/src/components/middle/message/Video.tsx b/src/components/middle/message/Video.tsx index a97cce38d..cbf137af3 100644 --- a/src/components/middle/message/Video.tsx +++ b/src/components/middle/message/Video.tsx @@ -10,7 +10,7 @@ import { getMediaFormat, getMediaThumbUri, getMediaTransferState, getVideoMediaHash, } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; -import { formatMediaDuration } from '../../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../../util/dates/oldDateFormat'; import * as mediaLoader from '../../../util/mediaLoader'; import { calculateExtendedPreviewDimensions, calculateVideoDimensions } from '../../common/helpers/mediaDimensions'; import { MIN_MEDIA_HEIGHT } from './helpers/mediaDimensions'; diff --git a/src/components/middle/message/actions/Gift.tsx b/src/components/middle/message/actions/Gift.tsx index f505a8d91..48052b989 100644 --- a/src/components/middle/message/actions/Gift.tsx +++ b/src/components/middle/message/actions/Gift.tsx @@ -13,7 +13,7 @@ import { selectGiftStickerForStars, selectGiftStickerForTon, } from '../../../../global/selectors'; -import { formatCountdownDays } from '../../../../util/dates/dateFormat'; +import { formatCountdownDays } from '../../../../util/dates/oldDateFormat'; import { formatCurrency } from '../../../../util/formatCurrency'; import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities'; diff --git a/src/components/middle/message/actions/GiveawayPrize.tsx b/src/components/middle/message/actions/GiveawayPrize.tsx index 0d3570ada..e4281f149 100644 --- a/src/components/middle/message/actions/GiveawayPrize.tsx +++ b/src/components/middle/message/actions/GiveawayPrize.tsx @@ -11,7 +11,7 @@ import { selectGiftStickerForDuration, selectGiftStickerForStars, } from '../../../../global/selectors'; -import { formatCountdownDays } from '../../../../util/dates/dateFormat'; +import { formatCountdownDays } from '../../../../util/dates/oldDateFormat'; import { renderPeerLink } from '../helpers/messageActions'; import { type ObserveFn } from '../../../../hooks/useIntersectionObserver'; diff --git a/src/components/middle/message/actions/StarGiftPurchaseOffer.tsx b/src/components/middle/message/actions/StarGiftPurchaseOffer.tsx index 544a7d836..77a432bd2 100644 --- a/src/components/middle/message/actions/StarGiftPurchaseOffer.tsx +++ b/src/components/middle/message/actions/StarGiftPurchaseOffer.tsx @@ -13,7 +13,7 @@ import { } from '../../../../global/selectors'; import { IS_TOUCH_ENV } from '../../../../util/browser/windowEnvironment'; import buildClassName from '../../../../util/buildClassName'; -import { formatShortHoursMinutes } from '../../../../util/dates/dateFormat'; +import { formatShortHoursMinutes } from '../../../../util/dates/oldDateFormat'; import { formatCurrencyAmountAsText } from '../../../../util/localization/format'; import { getServerTime } from '../../../../util/serverTime'; import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts'; diff --git a/src/components/middle/message/actions/SuggestedPostApproval.tsx b/src/components/middle/message/actions/SuggestedPostApproval.tsx index 016e2724c..7969afb32 100644 --- a/src/components/middle/message/actions/SuggestedPostApproval.tsx +++ b/src/components/middle/message/actions/SuggestedPostApproval.tsx @@ -11,7 +11,7 @@ import { selectIsMonoforumAdmin, selectMonoforumChannel, selectReplyMessage, selectSender } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; -import { formatScheduledDateTime, formatShortDuration } from '../../../../util/dates/dateFormat'; +import { formatScheduledDateTime, formatShortDuration } from '../../../../util/dates/oldDateFormat'; import { convertTonFromNanos } from '../../../../util/formatCurrency'; import { formatStarsAsText, formatTonAsText } from '../../../../util/localization/format'; import { getServerTime } from '../../../../util/serverTime'; diff --git a/src/components/middle/search/MiddleSearch.tsx b/src/components/middle/search/MiddleSearch.tsx index 3b2310b2f..ae1a88ce3 100644 --- a/src/components/middle/search/MiddleSearch.tsx +++ b/src/components/middle/search/MiddleSearch.tsx @@ -34,7 +34,7 @@ import { import { IS_IOS } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; import captureEscKeyListener from '../../../util/captureEscKeyListener'; -import { getDayStartAt } from '../../../util/dates/dateFormat'; +import { getDayStartAt } from '../../../util/dates/oldDateFormat'; import focusEditableElement from '../../../util/focusEditableElement'; import focusNoScroll from '../../../util/focusNoScroll'; import { getSearchResultKey, parseSearchResultKey, type SearchResultKey } from '../../../util/keys/searchResultKey'; diff --git a/src/components/modals/boost/BoostModal.tsx b/src/components/modals/boost/BoostModal.tsx index 244f93abe..4600bfdd9 100644 --- a/src/components/modals/boost/BoostModal.tsx +++ b/src/components/modals/boost/BoostModal.tsx @@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types'; import { getChatTitle, isChatAdmin, isChatChannel } from '../../../global/helpers'; import { selectChat, selectChatFullInfo, selectIsCurrentUserPremium } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatShortDuration } from '../../../util/dates/dateFormat'; +import { formatShortDuration } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import { getBoostProgressInfo } from '../../common/helpers/boostInfo'; import renderText from '../../common/helpers/renderText'; diff --git a/src/components/modals/collectible/CollectibleInfoModal.tsx b/src/components/modals/collectible/CollectibleInfoModal.tsx index 0097bc2eb..f73cd83bc 100644 --- a/src/components/modals/collectible/CollectibleInfoModal.tsx +++ b/src/components/modals/collectible/CollectibleInfoModal.tsx @@ -9,7 +9,7 @@ import type { ApiCountryCode } from '../../../api/types'; import type { TabState } from '../../../global/types'; import { copyTextToClipboard } from '../../../util/clipboard'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import { formatCurrencyAsString } from '../../../util/formatCurrency'; import { formatPhoneNumberWithCode } from '../../../util/phoneNumber'; import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets'; diff --git a/src/components/modals/frozenAccount/FrozenAccountModal.tsx b/src/components/modals/frozenAccount/FrozenAccountModal.tsx index bcfda0733..0bf6b861f 100644 --- a/src/components/modals/frozenAccount/FrozenAccountModal.tsx +++ b/src/components/modals/frozenAccount/FrozenAccountModal.tsx @@ -5,7 +5,7 @@ import type { TabState } from '../../../global/types'; import { getMainUsername } from '../../../global/helpers'; import { selectUser } from '../../../global/selectors'; -import { formatDateToString } from '../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../util/dates/oldDateFormat'; import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets'; import formatUsername from '../../common/helpers/formatUsername'; diff --git a/src/components/modals/gift/GiftComposer.tsx b/src/components/modals/gift/GiftComposer.tsx index 4b85bb514..7be021781 100644 --- a/src/components/modals/gift/GiftComposer.tsx +++ b/src/components/modals/gift/GiftComposer.tsx @@ -16,7 +16,7 @@ import { } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import buildStyle from '../../../util/buildStyle'; -import { formatCountdown } from '../../../util/dates/dateFormat'; +import { formatCountdown } from '../../../util/dates/oldDateFormat'; import { HOUR } from '../../../util/dates/units'; import { formatCurrency } from '../../../util/formatCurrency'; import { formatStarsAsIcon, getNextArrowReplacement } from '../../../util/localization/format'; diff --git a/src/components/modals/gift/StarGiftPriceDecreaseInfoModal.tsx b/src/components/modals/gift/StarGiftPriceDecreaseInfoModal.tsx index d33fe5a1b..2367378a1 100644 --- a/src/components/modals/gift/StarGiftPriceDecreaseInfoModal.tsx +++ b/src/components/modals/gift/StarGiftPriceDecreaseInfoModal.tsx @@ -4,7 +4,7 @@ import { getActions } from '../../../global'; import type { TabState } from '../../../global/types'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import { formatStarsAsIcon, formatStarsAsText } from '../../../util/localization/format'; import useCurrentOrPrev from '../../../hooks/useCurrentOrPrev'; diff --git a/src/components/modals/gift/UniqueGiftManageButtons.tsx b/src/components/modals/gift/UniqueGiftManageButtons.tsx index ca61072a9..a620b60a1 100644 --- a/src/components/modals/gift/UniqueGiftManageButtons.tsx +++ b/src/components/modals/gift/UniqueGiftManageButtons.tsx @@ -10,7 +10,7 @@ import type { import { DEFAULT_STATUS_ICON_ID } from '../../../config'; import { STARS_CURRENCY_CODE } from '../../../config'; import { selectTabState, selectUser } from '../../../global/selectors'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import useLang from '../../../hooks/useLang'; diff --git a/src/components/modals/gift/auction/GiftAuctionAcquiredModal.tsx b/src/components/modals/gift/auction/GiftAuctionAcquiredModal.tsx index bacbfdead..10a2bccbb 100644 --- a/src/components/modals/gift/auction/GiftAuctionAcquiredModal.tsx +++ b/src/components/modals/gift/auction/GiftAuctionAcquiredModal.tsx @@ -5,7 +5,7 @@ import type { ApiStarGiftAuctionAcquiredGift, ApiSticker } from '../../../../api import type { TabState } from '../../../../global/types'; import { selectTabState } from '../../../../global/selectors'; -import { formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import { formatStarsAsIcon } from '../../../../util/localization/format'; import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev'; diff --git a/src/components/modals/gift/auction/GiftAuctionModal.tsx b/src/components/modals/gift/auction/GiftAuctionModal.tsx index 96efc03c1..4ef9603ba 100644 --- a/src/components/modals/gift/auction/GiftAuctionModal.tsx +++ b/src/components/modals/gift/auction/GiftAuctionModal.tsx @@ -9,7 +9,7 @@ import type { TabState } from '../../../../global/types'; import { TME_LINK_PREFIX } from '../../../../config'; import { selectTabState } from '../../../../global/selectors'; import { copyTextToClipboard } from '../../../../util/clipboard'; -import { formatCountdown, formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatCountdown, formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import { HOUR } from '../../../../util/dates/units'; import { formatStarsAsIcon } from '../../../../util/localization/format'; import { getServerTime } from '../../../../util/serverTime'; diff --git a/src/components/modals/gift/info/GiftInfoModal.tsx b/src/components/modals/gift/info/GiftInfoModal.tsx index 95d1a6d39..c364ddb7e 100644 --- a/src/components/modals/gift/info/GiftInfoModal.tsx +++ b/src/components/modals/gift/info/GiftInfoModal.tsx @@ -15,7 +15,7 @@ import { getMainUsername } from '../../../../global/helpers/users'; import { selectPeer, selectUser } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; import { copyTextToClipboard } from '../../../../util/clipboard'; -import { formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import { formatCurrency, formatCurrencyAsString } from '../../../../util/formatCurrency'; import { formatStarsAsIcon, formatStarsAsText, formatTonAsIcon, formatTonAsText, diff --git a/src/components/modals/gift/locked/GiftLockedModal.tsx b/src/components/modals/gift/locked/GiftLockedModal.tsx index 37dfba4a3..66e9b4725 100644 --- a/src/components/modals/gift/locked/GiftLockedModal.tsx +++ b/src/components/modals/gift/locked/GiftLockedModal.tsx @@ -3,7 +3,7 @@ import { getActions } from '../../../../global'; import type { TabState } from '../../../../global/types'; -import { formatShortDuration } from '../../../../util/dates/dateFormat'; +import { formatShortDuration } from '../../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../../util/serverTime'; import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities'; diff --git a/src/components/modals/gift/value/GiftInfoValueModal.tsx b/src/components/modals/gift/value/GiftInfoValueModal.tsx index 5a0404395..aeb7b63fc 100644 --- a/src/components/modals/gift/value/GiftInfoValueModal.tsx +++ b/src/components/modals/gift/value/GiftInfoValueModal.tsx @@ -4,7 +4,7 @@ import { getActions } from '../../../../global'; import type { TabState } from '../../../../global/types'; -import { formatDateToString } from '../../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../../util/dates/oldDateFormat'; import { formatCurrencyAsString } from '../../../../util/formatCurrency'; import { formatStarsAsIcon } from '../../../../util/localization/format'; import { getGiftAttributes } from '../../../common/helpers/gifts'; diff --git a/src/components/modals/giftcode/GiftCodeModal.tsx b/src/components/modals/giftcode/GiftCodeModal.tsx index 5f50d76e5..82cd58496 100644 --- a/src/components/modals/giftcode/GiftCodeModal.tsx +++ b/src/components/modals/giftcode/GiftCodeModal.tsx @@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types'; import { TME_LINK_PREFIX } from '../../../config'; import { selectChatMessage, selectSender } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatCountdownDays, formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatCountdownDays, formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import renderText from '../../common/helpers/renderText'; import useLang from '../../../hooks/useLang'; diff --git a/src/components/modals/profileRating/ProfileRatingModal.tsx b/src/components/modals/profileRating/ProfileRatingModal.tsx index 25284b33a..2b9f72654 100644 --- a/src/components/modals/profileRating/ProfileRatingModal.tsx +++ b/src/components/modals/profileRating/ProfileRatingModal.tsx @@ -7,7 +7,7 @@ import type { TabState } from '../../../global/types'; import { getPeerTitle } from '../../../global/helpers/peers'; import { selectUser, selectUserFullInfo } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; -import { formatShortDuration } from '../../../util/dates/dateFormat'; +import { formatShortDuration } from '../../../util/dates/oldDateFormat'; import { getNextArrowReplacement } from '../../../util/localization/format'; import { getServerTime } from '../../../util/serverTime'; diff --git a/src/components/modals/stars/subscription/StarsSubscriptionItem.tsx b/src/components/modals/stars/subscription/StarsSubscriptionItem.tsx index 71d9b37b7..2f7abc9b0 100644 --- a/src/components/modals/stars/subscription/StarsSubscriptionItem.tsx +++ b/src/components/modals/stars/subscription/StarsSubscriptionItem.tsx @@ -9,7 +9,7 @@ import type { GlobalState } from '../../../../global/types'; import { NNBSP } from '../../../../config'; import { getPeerTitle } from '../../../../global/helpers/peers'; import { selectPeer } from '../../../../global/selectors'; -import { formatDateToString } from '../../../../util/dates/dateFormat'; +import { formatDateToString } from '../../../../util/dates/oldDateFormat'; import { formatInteger } from '../../../../util/textFormat'; import renderText from '../../../common/helpers/renderText'; diff --git a/src/components/modals/stars/subscription/StarsSubscriptionModal.tsx b/src/components/modals/stars/subscription/StarsSubscriptionModal.tsx index 7ac0a20ea..61f6e9f36 100644 --- a/src/components/modals/stars/subscription/StarsSubscriptionModal.tsx +++ b/src/components/modals/stars/subscription/StarsSubscriptionModal.tsx @@ -13,7 +13,7 @@ import { selectPeer, } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import useLang from '../../../../hooks/useLang'; import useLastCallback from '../../../../hooks/useLastCallback'; diff --git a/src/components/modals/stars/transaction/StarsTransactionItem.tsx b/src/components/modals/stars/transaction/StarsTransactionItem.tsx index a4982cd56..c5f185c9e 100644 --- a/src/components/modals/stars/transaction/StarsTransactionItem.tsx +++ b/src/components/modals/stars/transaction/StarsTransactionItem.tsx @@ -15,7 +15,7 @@ import { buildStarsTransactionCustomPeer, import { getPeerTitle } from '../../../../global/helpers/peers'; import { selectPeer } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import { CUSTOM_PEER_PREMIUM } from '../../../../util/objects/customPeer'; import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts'; import renderText from '../../../common/helpers/renderText'; diff --git a/src/components/modals/stars/transaction/StarsTransactionModal.tsx b/src/components/modals/stars/transaction/StarsTransactionModal.tsx index ef4b27bab..65feaf86b 100644 --- a/src/components/modals/stars/transaction/StarsTransactionModal.tsx +++ b/src/components/modals/stars/transaction/StarsTransactionModal.tsx @@ -24,7 +24,7 @@ import { } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; import { copyTextToClipboard } from '../../../../util/clipboard'; -import { formatDateTimeToString } from '../../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../../util/dates/oldDateFormat'; import { formatStarsAsIcon } from '../../../../util/localization/format'; import { formatPercent } from '../../../../util/textFormat'; import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts'; diff --git a/src/components/modals/suggestMessage/SuggestMessageModal.tsx b/src/components/modals/suggestMessage/SuggestMessageModal.tsx index 9de3c7252..73687b60f 100644 --- a/src/components/modals/suggestMessage/SuggestMessageModal.tsx +++ b/src/components/modals/suggestMessage/SuggestMessageModal.tsx @@ -16,7 +16,7 @@ import { import { selectIsMonoforumAdmin, selectPeer } from '../../../global/selectors'; import { selectDraft } from '../../../global/selectors/threads'; import buildClassName from '../../../util/buildClassName'; -import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat'; +import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/oldDateFormat'; import { convertTonFromNanos, convertTonToNanos } from '../../../util/formatCurrency'; import { formatStarsAsIcon, diff --git a/src/components/modals/suggestedPostApproval/SuggestedPostApprovalModal.tsx b/src/components/modals/suggestedPostApproval/SuggestedPostApprovalModal.tsx index 59c37ad08..069fb41a8 100644 --- a/src/components/modals/suggestedPostApproval/SuggestedPostApprovalModal.tsx +++ b/src/components/modals/suggestedPostApproval/SuggestedPostApprovalModal.tsx @@ -10,7 +10,7 @@ import { } from '../../../config'; import { getPeerFullTitle } from '../../../global/helpers/peers'; import { selectChatMessage, selectIsMonoforumAdmin, selectSender } from '../../../global/selectors'; -import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat'; +import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/oldDateFormat'; import { convertTonFromNanos } from '../../../util/formatCurrency'; import { formatStarsAsText, formatTonAsText } from '../../../util/localization/format'; import renderText from '../../common/helpers/renderText'; diff --git a/src/components/modals/suggestedStatus/SuggestedStatusModal.tsx b/src/components/modals/suggestedStatus/SuggestedStatusModal.tsx index fb89c5146..04c24b10a 100644 --- a/src/components/modals/suggestedStatus/SuggestedStatusModal.tsx +++ b/src/components/modals/suggestedStatus/SuggestedStatusModal.tsx @@ -6,7 +6,7 @@ import type { TabState } from '../../../global/types'; import { getUserFullName } from '../../../global/helpers'; import { selectUser } from '../../../global/selectors'; -import { formatShortDuration } from '../../../util/dates/dateFormat'; +import { formatShortDuration } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import { REM } from '../../common/helpers/mediaDimensions'; diff --git a/src/components/right/PollAnswerResults.tsx b/src/components/right/PollAnswerResults.tsx index aea9cc66e..8cc15a60d 100644 --- a/src/components/right/PollAnswerResults.tsx +++ b/src/components/right/PollAnswerResults.tsx @@ -14,7 +14,7 @@ import type { import type { PollVote } from '../../global/types/tabState'; import { selectTabState } from '../../global/selectors'; -import { formatMediaDateTime } from '../../util/dates/dateFormat'; +import { formatMediaDateTime } from '../../util/dates/oldDateFormat'; import { isUserId } from '../../util/entities/ids'; import { renderTextWithEntities } from '../common/helpers/renderTextWithEntities'; diff --git a/src/components/right/management/JoinRequest.tsx b/src/components/right/management/JoinRequest.tsx index 629cd492a..64c4e755d 100644 --- a/src/components/right/management/JoinRequest.tsx +++ b/src/components/right/management/JoinRequest.tsx @@ -7,7 +7,7 @@ import type { ApiUser } from '../../../api/types'; import { getUserFullName } from '../../../global/helpers'; import { selectUser } from '../../../global/selectors'; import { createClassNameBuilder } from '../../../util/buildClassName'; -import { formatHumanDate, formatTime, isToday } from '../../../util/dates/dateFormat'; +import { formatHumanDate, formatTime, isToday } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import useOldLang from '../../../hooks/useOldLang'; diff --git a/src/components/right/management/ManageInvite.tsx b/src/components/right/management/ManageInvite.tsx index 9b7521541..38d96fe45 100644 --- a/src/components/right/management/ManageInvite.tsx +++ b/src/components/right/management/ManageInvite.tsx @@ -7,7 +7,7 @@ import type { ApiExportedInvite } from '../../../api/types'; import { ManagementScreens } from '../../../types'; import { selectTabState } from '../../../global/selectors'; -import { formatFullDate, formatTime } from '../../../util/dates/dateFormat'; +import { formatFullDate, formatTime } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import useFlag from '../../../hooks/useFlag'; diff --git a/src/components/right/management/ManageInviteInfo.tsx b/src/components/right/management/ManageInviteInfo.tsx index c855533ce..1454058b4 100644 --- a/src/components/right/management/ManageInviteInfo.tsx +++ b/src/components/right/management/ManageInviteInfo.tsx @@ -6,7 +6,7 @@ import type { ApiChatInviteImporter, ApiExportedInvite } from '../../../api/type import { isChatChannel } from '../../../global/helpers'; import { selectChat, selectTabState } from '../../../global/selectors'; -import { formatFullDate, formatMediaDateTime, formatTime } from '../../../util/dates/dateFormat'; +import { formatFullDate, formatMediaDateTime, formatTime } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import useHistoryBack from '../../../hooks/useHistoryBack'; diff --git a/src/components/right/management/ManageInvites.tsx b/src/components/right/management/ManageInvites.tsx index b9216cda5..059caf5a8 100644 --- a/src/components/right/management/ManageInvites.tsx +++ b/src/components/right/management/ManageInvites.tsx @@ -11,7 +11,7 @@ import { STICKER_SIZE_INVITES, TME_LINK_PREFIX } from '../../../config'; import { getMainUsername, isChatChannel } from '../../../global/helpers'; import { selectChat, selectTabState } from '../../../global/selectors'; import { copyTextToClipboard } from '../../../util/clipboard'; -import { formatCountdown, MILLISECONDS_IN_DAY } from '../../../util/dates/dateFormat'; +import { formatCountdown, MILLISECONDS_IN_DAY } from '../../../util/dates/oldDateFormat'; import { getServerTime } from '../../../util/serverTime'; import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets'; diff --git a/src/components/right/statistics/BoostStatistics.tsx b/src/components/right/statistics/BoostStatistics.tsx index 0ae05bae1..f064e5cb8 100644 --- a/src/components/right/statistics/BoostStatistics.tsx +++ b/src/components/right/statistics/BoostStatistics.tsx @@ -10,7 +10,7 @@ import { isChatChannel } from '../../../global/helpers'; import { selectChat, selectIsGiveawayGiftsPurchaseAvailable, selectTabState } from '../../../global/selectors'; import { selectSharedSettings } from '../../../global/selectors/sharedState.ts'; import buildClassName from '../../../util/buildClassName'; -import { formatDateAtTime } from '../../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../../util/dates/oldDateFormat'; import { resolveTransitionName } from '../../../util/resolveTransitionName.ts'; import { formatInteger } from '../../../util/textFormat'; import { getBoostProgressInfo } from '../../common/helpers/boostInfo'; diff --git a/src/components/right/statistics/StatisticsOverview.tsx b/src/components/right/statistics/StatisticsOverview.tsx index 25f62276a..c8db1cad1 100644 --- a/src/components/right/statistics/StatisticsOverview.tsx +++ b/src/components/right/statistics/StatisticsOverview.tsx @@ -8,7 +8,7 @@ import type { } from '../../../api/types'; import buildClassName from '../../../util/buildClassName'; -import { formatFullDate } from '../../../util/dates/dateFormat'; +import { formatFullDate } from '../../../util/dates/oldDateFormat'; import { convertTonFromNanos } from '../../../util/formatCurrency'; import { formatInteger, formatIntegerCompact } from '../../../util/textFormat'; diff --git a/src/components/right/statistics/StatisticsRecentMessage.tsx b/src/components/right/statistics/StatisticsRecentMessage.tsx index 86146828b..3ff4881da 100644 --- a/src/components/right/statistics/StatisticsRecentMessage.tsx +++ b/src/components/right/statistics/StatisticsRecentMessage.tsx @@ -9,7 +9,7 @@ import { getMessageVideo, } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import { type LangFn } from '../../../util/localization'; import { renderMessageSummary } from '../../common/helpers/renderMessageText'; diff --git a/src/components/right/statistics/StatisticsRecentStory.tsx b/src/components/right/statistics/StatisticsRecentStory.tsx index ff772570e..635d8526b 100644 --- a/src/components/right/statistics/StatisticsRecentStory.tsx +++ b/src/components/right/statistics/StatisticsRecentStory.tsx @@ -10,7 +10,7 @@ import type { OldLangFn } from '../../../hooks/useOldLang'; import { getStoryMediaHash } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString } from '../../../util/dates/dateFormat'; +import { formatDateTimeToString } from '../../../util/dates/oldDateFormat'; import useLastCallback from '../../../hooks/useLastCallback'; import useMedia from '../../../hooks/useMedia'; diff --git a/src/components/story/MediaStory.tsx b/src/components/story/MediaStory.tsx index ad691be74..3b0e65f01 100644 --- a/src/components/story/MediaStory.tsx +++ b/src/components/story/MediaStory.tsx @@ -8,7 +8,7 @@ import type { ApiTypeStory } from '../../api/types'; import { getStoryMediaHash } from '../../global/helpers'; import { selectChat, selectPinnedStories } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import stopEvent from '../../util/stopEvent'; import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur'; diff --git a/src/components/story/Story.tsx b/src/components/story/Story.tsx index 527c4fab5..01698487e 100644 --- a/src/components/story/Story.tsx +++ b/src/components/story/Story.tsx @@ -33,7 +33,7 @@ import { import { IS_SAFARI } from '../../util/browser/windowEnvironment'; import buildClassName from '../../util/buildClassName'; import captureKeyboardListeners from '../../util/captureKeyboardListeners'; -import { formatMediaDuration, formatRelativePastTime } from '../../util/dates/dateFormat'; +import { formatMediaDuration, formatRelativePastTime } from '../../util/dates/oldDateFormat'; import download from '../../util/download'; import { isUserId } from '../../util/entities/ids'; import { formatStarsAsIcon } from '../../util/localization/format'; diff --git a/src/components/story/StoryRibbonButton.tsx b/src/components/story/StoryRibbonButton.tsx index 6b04827d8..6ed39c48c 100644 --- a/src/components/story/StoryRibbonButton.tsx +++ b/src/components/story/StoryRibbonButton.tsx @@ -6,7 +6,7 @@ import { StoryViewerOrigin } from '../../types'; import { getPeerTitle } from '../../global/helpers/peers'; import buildClassName from '../../util/buildClassName'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import { isUserId } from '../../util/entities/ids'; import { getServerTime } from '../../util/serverTime'; import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur'; diff --git a/src/components/story/StoryView.tsx b/src/components/story/StoryView.tsx index 0081f0610..2a89133ec 100644 --- a/src/components/story/StoryView.tsx +++ b/src/components/story/StoryView.tsx @@ -9,7 +9,7 @@ import type { IconName } from '../../types/icons'; import { getUserFullName } from '../../global/helpers'; import { selectPeer } from '../../global/selectors'; import buildClassName from '../../util/buildClassName'; -import { formatDateAtTime } from '../../util/dates/dateFormat'; +import { formatDateAtTime } from '../../util/dates/oldDateFormat'; import { isUserId } from '../../util/entities/ids'; import { REM } from '../common/helpers/mediaDimensions'; diff --git a/src/components/test/TestDateFormat.module.scss b/src/components/test/TestDateFormat.module.scss new file mode 100644 index 000000000..2ff22c61a --- /dev/null +++ b/src/components/test/TestDateFormat.module.scss @@ -0,0 +1,29 @@ +.root { + overflow: auto; + overscroll-behavior: contain; + + box-sizing: border-box; + height: 100%; + min-height: 0; + padding: 1rem; + + background: var(--color-background); +} + +.table { + border-collapse: collapse; + width: 100%; + margin-bottom: 1.5rem; +} + +.cell { + padding: 0.375rem 0.5rem; + border: 1px solid var(--color-borders); + text-align: left; + vertical-align: top; +} + +.code { + overflow-wrap: anywhere; + white-space: pre-wrap; +} diff --git a/src/components/test/TestDateFormat.tsx b/src/components/test/TestDateFormat.tsx new file mode 100644 index 000000000..04d75d107 --- /dev/null +++ b/src/components/test/TestDateFormat.tsx @@ -0,0 +1,128 @@ +import type { FormatDateTimeOptions } from '../../util/localization/dateFormat'; + +import buildClassName from '../../util/buildClassName'; +import { formatDateTime } from '../../util/localization/dateFormat'; + +import useLang from '../../hooks/useLang'; + +import styles from './TestDateFormat.module.scss'; + +type Row = { + label: string; + value: string; +}; + +const ANCHOR_DATE = new Date(2026, 2, 16, 12, 34, 56); +const ANCHOR_TIMESTAMP = ANCHOR_DATE.getTime(); + +const ABSOLUTE_CASES: Array<{ label: string; options: FormatDateTimeOptions }> = [ + { label: 'default', options: {} }, + { label: 'date: numeric', options: { date: 'numeric' } }, + { label: 'date: short', options: { date: 'short' } }, + { label: 'date: long', options: { date: 'long' } }, + { label: 'date: short, no year', options: { date: 'short', includeYear: false } }, + { label: 'date: short, no day', options: { date: 'short', includeDay: false } }, + { label: 'date: long, no year', options: { date: 'long', includeYear: false } }, + { label: 'date: long, no day', options: { date: 'long', includeDay: false } }, + { label: 'time: short', options: { time: 'short' } }, + { label: 'time: long', options: { time: 'long' } }, + { label: 'weekday: short', options: { weekday: 'short' } }, + { label: 'weekday: long', options: { weekday: 'long' } }, + { label: 'weekday: short + date: short', options: { weekday: 'short', date: 'short' } }, + { label: 'weekday: long + date: long', options: { weekday: 'long', date: 'long' } }, + { label: 'weekday: short + time: short', options: { weekday: 'short', time: 'short' } }, + { label: 'date: short + time: short', options: { date: 'short', time: 'short' } }, + { label: 'date: short + time: long', options: { date: 'short', time: 'long' } }, + { label: 'date: long + time: short', options: { date: 'long', time: 'short' } }, + { label: 'date: long + time: long', options: { date: 'long', time: 'long' } }, + { + label: 'weekday + date: short + time: short', + options: { weekday: 'short', date: 'short', time: 'short' }, + }, + { + label: 'weekday: long + date: long + time: long', + options: { weekday: 'long', date: 'long', time: 'long' }, + }, +]; + +const RELATIVE_CASES = [ + { label: '30 seconds later', startDate: new Date(2026, 2, 16, 12, 35, 26) }, + { label: '5 minutes later', startDate: new Date(2026, 2, 16, 12, 39, 56) }, + { label: '3 hours later', startDate: new Date(2026, 2, 16, 15, 34, 56) }, + { label: 'tomorrow', startDate: new Date(2026, 2, 17, 12, 34, 56) }, + { label: '2 days later', startDate: new Date(2026, 2, 18, 12, 34, 56) }, + { label: '10 days later', startDate: new Date(2026, 2, 26, 12, 34, 56) }, + { label: '45 seconds earlier', startDate: new Date(2026, 2, 16, 12, 34, 11) }, + { label: '2 hours earlier', startDate: new Date(2026, 2, 16, 10, 34, 56) }, + { label: 'yesterday', startDate: new Date(2026, 2, 15, 12, 34, 56) }, + { label: '3 days earlier', startDate: new Date(2026, 2, 13, 12, 34, 56) }, +]; + +function DebugTable({ rows }: { rows: Row[] }) { + return ( + + + + + + + + + {rows.map(({ label, value }) => ( + + + + + ))} + +
CaseOutput
{label}{value}
+ ); +} + +const DateFormatTest = () => { + const lang = useLang(); + const languageInfo = lang.languageInfo; + + const absoluteRows: Row[] = ABSOLUTE_CASES.map(({ label, options }) => ({ + label, + value: formatDateTime(lang, ANCHOR_DATE, options), + })); + + const relativeRows: Row[] = RELATIVE_CASES.map(({ label, startDate }) => { + const startDateLabel = startDate.toLocaleString(); + + return { + label: `${label} (${startDateLabel})`, + value: formatDateTime(lang, startDate, { relative: 'auto', anchorDate: ANCHOR_DATE }), + }; + }); + + const contextRows: Row[] = [ + { label: 'lang.code', value: lang.code }, + { label: 'lang.rawCode', value: lang.rawCode }, + { label: 'lang.languageInfo ready', value: String(Boolean(languageInfo)) }, + { label: 'lang.languageInfo.pluralCode', value: languageInfo?.pluralCode || '' }, + { label: 'lang.timeFormat', value: lang.timeFormat }, + { label: 'anchorDate.toString()', value: ANCHOR_DATE.toString() }, + { label: 'anchorDate.toISOString()', value: ANCHOR_DATE.toISOString() }, + { label: 'anchorDate.getTime()', value: String(ANCHOR_TIMESTAMP) }, + ]; + + return ( +
+

Date Format Test

+

Formats one fixed date through the new localized date formatter in as many useful combinations as possible.

+ +

Context

+ + +

Absolute Options

+ + +

Relative Formatting

+ +
+ ); +}; + +export default DateFormatTest; diff --git a/src/components/test/TestDateFormatPerf.tsx b/src/components/test/TestDateFormatPerf.tsx new file mode 100644 index 000000000..1c75dea32 --- /dev/null +++ b/src/components/test/TestDateFormatPerf.tsx @@ -0,0 +1,317 @@ +import { useEffect, useState } from '../../lib/teact/teact'; + +import buildClassName from '../../util/buildClassName'; +import { + formatDateTimeToString as oldFormatDateTimeToString, + formatDateToString as oldFormatDateToString, + formatPastTimeShort as oldFormatPastTimeShort, + formatTime as oldFormatTime, +} from '../../util/dates/oldDateFormat'; +import { formatDateTime } from '../../util/localization/dateFormat'; + +import useLang from '../../hooks/useLang'; +import useOldLang, { type OldLangFn } from '../../hooks/useOldLang'; + +import styles from './TestDateFormat.module.scss'; + +const BENCHMARK_COUNT = 10000; +const RANDOM_SEED = 123456789; +const DAY_IN_MS = 24 * 60 * 60 * 1000; + +type NewLangFn = ReturnType; +type BenchmarkFormatter = (date: Date) => string; +type BenchmarkCase = { + name: string; + oldFormatter: BenchmarkFormatter; + newFormatter: BenchmarkFormatter; +}; +type Measurement = { + totalMs: number; + perCallMs: number; + checksum: number; + sample: string; +}; +type BenchmarkResult = { + name: string; + old: Measurement; + new: Measurement; +}; + +function createSeededRandom(seed: number) { + let value = seed >>> 0; + + return () => { + value = (value * 1664525 + 1013904223) >>> 0; + return value / 0x100000000; + }; +} + +function generateRandomDates(count: number, now: Date) { + const random = createSeededRandom(RANDOM_SEED); + const dates: Date[] = []; + + for (let i = 0; i < count; i++) { + const bucket = random(); + let offsetMs: number; + + if (bucket < 0.45) { + offsetMs = -Math.floor(random() * DAY_IN_MS); + } else if (bucket < 0.8) { + offsetMs = -Math.floor(random() * 7 * DAY_IN_MS); + } else if (bucket < 0.97) { + offsetMs = -Math.floor((7 + random() * 358) * DAY_IN_MS); + } else { + offsetMs = Math.floor(random() * 2 * DAY_IN_MS); + } + + dates.push(new Date(now.getTime() + offsetMs)); + } + + return dates; +} + +function getDayStart(date: Date) { + const result = new Date(date); + result.setHours(0, 0, 0, 0); + return result; +} + +function formatPastTimeShortWithNewCore(lang: NewLangFn, date: Date) { + const time = formatDateTime(lang, date, { time: 'short' }); + + const today = getDayStart(new Date()); + if (date >= today) { + return time; + } + + const weekAgo = new Date(today); + weekAgo.setDate(today.getDate() - 7); + if (date >= weekAgo) { + return formatDateTime(lang, date, { weekday: 'short' }); + } + + return formatDateTime(lang, date, { + date: 'short', + includeYear: date.getFullYear() === today.getFullYear() ? false : undefined, + }); +} + +function createBenchmarkCases(oldLang: OldLangFn, lang: NewLangFn): BenchmarkCase[] { + return [ + { + name: 'time short', + oldFormatter: (date) => oldFormatTime(oldLang, date), + newFormatter: (date) => formatDateTime(lang, date, { time: 'short' }), + }, + { + name: 'past time short', + oldFormatter: (date) => oldFormatPastTimeShort(oldLang, date), + newFormatter: (date) => formatPastTimeShortWithNewCore(lang, date), + }, + { + name: 'date short', + oldFormatter: (date) => oldFormatDateToString(date, oldLang.code, false, 'short'), + newFormatter: (date) => formatDateTime(lang, date, { date: 'short' }), + }, + { + name: 'date + time short', + oldFormatter: (date) => oldFormatDateTimeToString(date, oldLang.code, true, oldLang.timeFormat), + newFormatter: (date) => formatDateTime(lang, date, { date: 'short', time: 'short' }), + }, + ]; +} + +function measureFormatting(dates: Date[], formatter: BenchmarkFormatter): Measurement { + let checksum = 0; + let sample = ''; + + const start = performance.now(); + for (let i = 0; i < dates.length; i++) { + const value = formatter(dates[i]); + + if (!sample) { + sample = value; + } + + checksum = ((checksum * 33) + value.length + value.charCodeAt(0)) >>> 0; + } + const totalMs = performance.now() - start; + + return { + totalMs, + perCallMs: totalMs / dates.length, + checksum, + sample, + }; +} + +function warmUp(dates: Date[], formatter: BenchmarkFormatter) { + const warmUpCount = Math.min(250, dates.length); + + for (let i = 0; i < warmUpCount; i++) { + formatter(dates[i]); + } +} + +function summarizeDates(dates: Date[]) { + const today = getDayStart(new Date()).getTime(); + const weekAgo = today - (7 * DAY_IN_MS); + + let todayCount = 0; + let lastWeekCount = 0; + let olderCount = 0; + let futureCount = 0; + + for (let i = 0; i < dates.length; i++) { + const timestamp = dates[i].getTime(); + + if (timestamp >= today) { + if (timestamp >= Date.now()) { + futureCount++; + } else { + todayCount++; + } + continue; + } + + if (timestamp >= weekAgo) { + lastWeekCount++; + continue; + } + + olderCount++; + } + + return { + today: todayCount, + lastWeek: lastWeekCount, + older: olderCount, + future: futureCount, + }; +} + +function logBenchmarkResults( + lang: NewLangFn, + oldLang: OldLangFn, + now: Date, + dates: Date[], + results: BenchmarkResult[], +) { + const formattedResults = Object.fromEntries(results.map((result) => { + return [result.name, { + old: { + totalMs: Number(result.old.totalMs.toFixed(2)), + perCallMs: Number(result.old.perCallMs.toFixed(8)), + checksum: result.old.checksum, + sample: result.old.sample, + }, + new: { + totalMs: Number(result.new.totalMs.toFixed(2)), + perCallMs: Number(result.new.perCallMs.toFixed(8)), + checksum: result.new.checksum, + sample: result.new.sample, + }, + newVsOld: Number((result.new.totalMs / result.old.totalMs).toFixed(2)), + }]; + })); + const label = [ + '[TestDateFormatPerf]', + `lang=${lang.code}`, + `oldLang=${oldLang.code}`, + `timeFormat=${lang.timeFormat}`, + `N=${BENCHMARK_COUNT}`, + ].join(' '); + + // eslint-disable-next-line no-console + console.group(label); + // eslint-disable-next-line no-console + console.log('dataset', { + seed: RANDOM_SEED, + generatedAt: now.toISOString(), + distribution: summarizeDates(dates), + }); + // eslint-disable-next-line no-console + console.log('results', formattedResults); + // eslint-disable-next-line no-console + console.groupEnd(); +} + +const TestDateFormatPerf = () => { + const lang = useLang(); + const oldLang = useOldLang(); + + const [lastRunAt, setLastRunAt] = useState(); + const [runId, setRunId] = useState(0); + + useEffect(() => { + let isActive = true; + + const runBenchmarks = () => { + const now = new Date(); + const dates = generateRandomDates(BENCHMARK_COUNT, now); + const benchmarkCases = createBenchmarkCases(oldLang, lang); + + const results: BenchmarkResult[] = benchmarkCases.map((benchmarkCase) => { + warmUp(dates, benchmarkCase.oldFormatter); + warmUp(dates, benchmarkCase.newFormatter); + + return { + name: benchmarkCase.name, + old: measureFormatting(dates, benchmarkCase.oldFormatter), + new: measureFormatting(dates, benchmarkCase.newFormatter), + }; + }); + + logBenchmarkResults(lang, oldLang, now, dates, results); + + if (isActive) { + setLastRunAt(new Date().toLocaleTimeString()); + } + }; + + const frameId = window.requestAnimationFrame(runBenchmarks); + + return () => { + isActive = false; + + if (frameId !== undefined) { + window.cancelAnimationFrame(frameId); + } + }; + }, [lang, oldLang, runId]); + + return ( +
+

Date Format Perf

+

Generates 10,000 random dates, benchmarks old and new formatting paths, and prints results to the console.

+

+ Current context: + {' '} + {`${lang.code} / ${lang.timeFormat}`} +

+

+ Benchmarks: + {' '} + formatTime + {', '} + formatPastTimeShort + {', '} + date short + {', '} + date + time short +

+ {lastRunAt && ( +

+ Last run: + {' '} + {lastRunAt} +

+ )} + +
+ ); +}; + +export default TestDateFormatPerf; diff --git a/src/components/ui/RoundTimer.tsx b/src/components/ui/RoundTimer.tsx index ba805c2cb..1786076f6 100644 --- a/src/components/ui/RoundTimer.tsx +++ b/src/components/ui/RoundTimer.tsx @@ -1,7 +1,7 @@ import { memo, useEffect, useState } from '../../lib/teact/teact'; import buildClassName from '../../util/buildClassName'; -import { formatCountdownShort } from '../../util/dates/dateFormat'; +import { formatCountdownShort } from '../../util/dates/oldDateFormat'; import useInterval from '../../hooks/schedulers/useInterval'; import useOldLang from '../../hooks/useOldLang'; diff --git a/src/components/ui/TextTimer.tsx b/src/components/ui/TextTimer.tsx index 7b5671823..46abc224b 100644 --- a/src/components/ui/TextTimer.tsx +++ b/src/components/ui/TextTimer.tsx @@ -1,6 +1,6 @@ import { useEffect } from '../../lib/teact/teact'; -import { formatMediaDuration } from '../../util/dates/dateFormat'; +import { formatMediaDuration } from '../../util/dates/oldDateFormat'; import { getServerTime } from '../../util/serverTime'; import useInterval from '../../hooks/schedulers/useInterval'; diff --git a/src/config.ts b/src/config.ts index 83268fe2f..55b397e57 100644 --- a/src/config.ts +++ b/src/config.ts @@ -250,7 +250,8 @@ export const DEFAULT_TOPIC_ICON_STICKER_ID = 'topic-default-icon'; export const DEFAULT_STATUS_ICON_ID = 'status-default-icon'; export const EMOJI_IMG_REGEX = /]+alt="([^"]+)"(?![^>]*data-document-id)[^>]*>/gm; -export const BASE_EMOJI_KEYWORD_LANG = 'en'; +export const FALLBACK_LANG_CODE = 'en'; +export const BASE_EMOJI_KEYWORD_LANG = FALLBACK_LANG_CODE; export const MENU_TRANSITION_DURATION = 200; export const SLIDE_TRANSITION_DURATION = 450; diff --git a/src/global/actions/api/globalSearch.ts b/src/global/actions/api/globalSearch.ts index 4a4f2c20a..b8756faa4 100644 --- a/src/global/actions/api/globalSearch.ts +++ b/src/global/actions/api/globalSearch.ts @@ -8,7 +8,7 @@ import type { import type { ActionReturnType, GlobalState, TabArgs } from '../../types'; import { GLOBAL_SEARCH_SLICE, GLOBAL_TOPIC_SEARCH_SLICE } from '../../../config'; -import { timestampPlusDay } from '../../../util/dates/dateFormat'; +import { timestampPlusDay } from '../../../util/dates/oldDateFormat'; import { isDeepLink, tryParseDeepLink } from '../../../util/deepLinkParser'; import { toChannelId } from '../../../util/entities/ids'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; diff --git a/src/global/actions/api/settings.ts b/src/global/actions/api/settings.ts index a20925206..15ea01856 100644 --- a/src/global/actions/api/settings.ts +++ b/src/global/actions/api/settings.ts @@ -16,7 +16,6 @@ import { toCredentialCreationOptions } from '../../../util/browser/passkeys'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; import { buildCollectionByKey } from '../../../util/iteratees'; import { requestPermission, subscribe, unsubscribe } from '../../../util/notifications'; -import { setTimeFormat } from '../../../util/oldLangProvider'; import requestActionTimeout from '../../../util/requestActionTimeout'; import { getServerTime } from '../../../util/serverTime'; import { callApi } from '../../../api/gramjs'; @@ -642,7 +641,6 @@ addActionHandler('ensureTimeFormat', async (global, actions): Promise => { const timeFormat = COUNTRIES_WITH_12H_TIME_FORMAT .has(global.auth.nearestCountry.toUpperCase()) ? '12h' : '24h'; actions.setSharedSettingOption({ timeFormat }); - setTimeFormat(timeFormat); } if (selectSharedSettings(global).wasTimeFormatSetManually) { @@ -653,7 +651,6 @@ addActionHandler('ensureTimeFormat', async (global, actions): Promise => { if (nearestCountryCode) { const timeFormat = COUNTRIES_WITH_12H_TIME_FORMAT.has(nearestCountryCode.toUpperCase()) ? '12h' : '24h'; actions.setSharedSettingOption({ timeFormat }); - setTimeFormat(timeFormat); } }); diff --git a/src/global/actions/ui/initial.ts b/src/global/actions/ui/initial.ts index 504fb1e19..4ec3bb3e0 100644 --- a/src/global/actions/ui/initial.ts +++ b/src/global/actions/ui/initial.ts @@ -12,6 +12,7 @@ import { } from '../../../util/browser/windowEnvironment'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; import generateUniqueId from '../../../util/generateUniqueId'; +import { setTimeFormat as setLocalizedTimeFormat } from '../../../util/localization'; import { subscribe, unsubscribe } from '../../../util/notifications'; import { oldSetLanguage } from '../../../util/oldLangProvider'; import { decryptSessionByCurrentHash } from '../../../util/passcode'; @@ -139,7 +140,9 @@ addCallback((global: GlobalState) => { shouldInit: false, }, tabState.id); - const { messageTextSize, language, shouldUseSystemTheme } = selectSharedSettings(global); + const { + messageTextSize, language, shouldUseSystemTheme, timeFormat, + } = selectSharedSettings(global); const globalTheme = selectTheme(global); const systemTheme = getSystemTheme(); @@ -148,6 +151,7 @@ addCallback((global: GlobalState) => { const performanceType = selectPerformanceSettings(global); void oldSetLanguage(language as LangCode, undefined); + setLocalizedTimeFormat(timeFormat); requestMutation(() => { document.documentElement.style.setProperty( diff --git a/src/global/actions/ui/settings.ts b/src/global/actions/ui/settings.ts index 7ed76fc74..51a4007f4 100644 --- a/src/global/actions/ui/settings.ts +++ b/src/global/actions/ui/settings.ts @@ -7,7 +7,8 @@ import { requestMutation } from '../../../lib/fasterdom/fasterdom'; import { IS_IOS } from '../../../util/browser/windowEnvironment'; import { disableDebugConsole, initDebugConsole } from '../../../util/debugConsole'; import { getCurrentTabId } from '../../../util/establishMultitabRole'; -import { oldSetLanguage, setTimeFormat } from '../../../util/oldLangProvider'; +import { setTimeFormat as setLocalizedTimeFormat } from '../../../util/localization'; +import { oldSetLanguage, setTimeFormat as setLegacyTimeFormat } from '../../../util/oldLangProvider'; import { applyPerformanceSettings } from '../../../util/perfomanceSettings'; import switchTheme from '../../../util/switchTheme'; import { updatePeerColors } from '../../../util/theme'; @@ -59,7 +60,8 @@ addCallback((global: GlobalState) => { } if (sharedSettings.timeFormat !== oldSharedSettings.timeFormat) { - setTimeFormat(sharedSettings.timeFormat); + setLocalizedTimeFormat(sharedSettings.timeFormat); + setLegacyTimeFormat(sharedSettings.timeFormat); } if (sharedSettings.messageTextSize !== oldSharedSettings.messageTextSize) { diff --git a/src/global/helpers/chats.ts b/src/global/helpers/chats.ts index ffd4ce471..77e5fcb22 100644 --- a/src/global/helpers/chats.ts +++ b/src/global/helpers/chats.ts @@ -25,7 +25,7 @@ import { ARCHIVED_FOLDER_ID, GENERAL_TOPIC_ID, REPLIES_USER_ID, TME_LINK_PREFIX, VERIFICATION_CODES_USER_ID, } from '../../config'; -import { formatDateToString, formatTime } from '../../util/dates/dateFormat'; +import { formatDateToString, formatTime } from '../../util/dates/oldDateFormat'; import { getPeerIdDividend, isUserId } from '../../util/entities/ids'; import { getServerTime } from '../../util/serverTime'; import { selectIsChatRestricted } from '../selectors'; diff --git a/src/global/helpers/users.ts b/src/global/helpers/users.ts index 97523713d..38d4ef7ac 100644 --- a/src/global/helpers/users.ts +++ b/src/global/helpers/users.ts @@ -2,7 +2,7 @@ import type { ApiPeer, ApiUser, ApiUserStatus } from '../../api/types'; import type { OldLangFn } from '../../hooks/useOldLang'; import { ANONYMOUS_USER_ID, SERVICE_NOTIFICATIONS_USER_ID } from '../../config'; -import { formatFullDate, formatTime } from '../../util/dates/dateFormat'; +import { formatFullDate, formatTime } from '../../util/dates/oldDateFormat'; import { DAY } from '../../util/dates/units'; import { orderBy } from '../../util/iteratees'; import { formatPhoneNumber } from '../../util/phoneNumber'; diff --git a/src/hooks/useSchedule.tsx b/src/hooks/useSchedule.tsx index 6ce1880f6..b571020aa 100644 --- a/src/hooks/useSchedule.tsx +++ b/src/hooks/useSchedule.tsx @@ -3,7 +3,7 @@ import { useState } from '../lib/teact/teact'; import type { RepeatedMessageMode } from '../util/scheduledMessages'; import { SCHEDULED_WHEN_ONLINE } from '../config'; -import { getDayStartAt } from '../util/dates/dateFormat'; +import { getDayStartAt } from '../util/dates/oldDateFormat'; import { getRepeatModeFromSeconds, getRepeatPeriodSeconds } from '../util/scheduledMessages'; import { getServerTimeOffset } from '../util/serverTime'; import useLastCallback from './useLastCallback'; diff --git a/src/util/data/readFallbackStrings.ts b/src/util/data/readFallbackStrings.ts index b8768826a..3b3b36065 100644 --- a/src/util/data/readFallbackStrings.ts +++ b/src/util/data/readFallbackStrings.ts @@ -2,11 +2,11 @@ import type { ApiLanguage, CachedLangData, LangPack, LangPackStringValuePlural, } from '../../api/types'; +import { FALLBACK_LANG_CODE } from '../../config'; import readStrings from './readStrings'; -const FALLBACK_LANG_CODE = 'en'; const FALLBACK_VERSION = 0; -const FALLBACK_TRANSLATE_URL = 'https://translations.telegram.org/en/weba'; +const FALLBACK_TRANSLATE_URL = `https://translations.telegram.org/${FALLBACK_LANG_CODE}/weba`; export default async function readFallbackStrings(forLocalScript?: boolean): Promise { let fileData; diff --git a/src/util/dates/dateFormat.ts b/src/util/dates/oldDateFormat.ts similarity index 100% rename from src/util/dates/dateFormat.ts rename to src/util/dates/oldDateFormat.ts diff --git a/src/util/formatCurrency.tsx b/src/util/formatCurrency.tsx index c1d5c501a..3cd4aec5f 100644 --- a/src/util/formatCurrency.tsx +++ b/src/util/formatCurrency.tsx @@ -2,7 +2,7 @@ import { type TeactNode } from '../lib/teact/teact'; import type { LangFn } from './localization'; -import { STARS_CURRENCY_CODE, TON_CURRENCY_CODE } from '../config'; +import { FALLBACK_LANG_CODE, STARS_CURRENCY_CODE, TON_CURRENCY_CODE } from '../config'; import { formatStarsAsIcon, formatTonAsIcon } from './localization/format'; export function convertCurrencyFromBaseUnit(amount: number, currency: string) { @@ -52,7 +52,7 @@ export function convertTonToUsd(amount: number, usdRate: number, isInNanos: bool export function formatCurrencyAsString( totalPrice: number, currency: string, - locale: string = 'en', + locale: string = FALLBACK_LANG_CODE, options?: { shouldOmitFractions?: boolean; }, diff --git a/src/util/localization/dateFormat.ts b/src/util/localization/dateFormat.ts new file mode 100644 index 000000000..d348560ed --- /dev/null +++ b/src/util/localization/dateFormat.ts @@ -0,0 +1,248 @@ +import type { TimeFormat } from '../../types'; +import type { LangFn } from './types'; + +import { FALLBACK_LANG_CODE } from '../../config'; + +import LimitedMap from '../primitives/LimitedMap'; + +type DateStyle = 'short' | 'long' | 'numeric' | false; +type TimeStyle = 'short' | 'long' | false; +type WeekdayStyle = 'short' | 'long' | boolean; +type RelativeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week'; +type RelativeType = 'numeric' | 'auto'; +type RelativePart = { unit: RelativeUnit; value: number }; + +export interface FormatDateTimeOptions { + date?: DateStyle; + time?: TimeStyle; + weekday?: WeekdayStyle; + /** + * The type of relative time formatting to use. + * - 'numeric' uses the numeric format (e.g. "1 day ago", "2 weeks ago"). + * - 'auto' output may use more idiomatic phrasing such as "yesterday". + */ + relative?: RelativeType; + /** + * The date to use as the anchor for relative formatting. Usually the current date. + */ + anchorDate?: Date; + includeYear?: boolean; + includeDay?: boolean; + maxRelativeDays?: number; +} + +const RESULT_CACHE_LIMIT = 200; +const DAY_IN_SECONDS = 24 * 60 * 60; + +const dateTimeFormatters = new Map(); +const relativeTimeFormatters = new Map(); +const resultCache = new LimitedMap(RESULT_CACHE_LIMIT); + +export function resetDateFormatCache() { + dateTimeFormatters.clear(); + relativeTimeFormatters.clear(); + resultCache.clear(); +} + +export function formatDateTime(lang: LangFn, date: Date, options: FormatDateTimeOptions = {}) { + if (options.relative) { + const relative = formatRelativeDateTime( + lang, date, options.anchorDate, options.relative, { + maxRelativeDays: options.maxRelativeDays, + }); + if (relative) { + return relative; + } + } + + return formatAbsoluteDateTime(lang, date, options); +} + +function formatAbsoluteDateTime(lang: LangFn, date: Date, options: FormatDateTimeOptions) { + const intlOptions = buildAbsoluteFormatterOptions(lang, options); + const cacheKey = [ + 'formatDateTime', + lang.code, + lang.timeFormat, + date.getTime(), + serializeRecord({ + date: options.date ?? false, + time: options.time ?? false, + weekday: options.weekday, + includeYear: options.includeYear, + includeDay: options.includeDay, + }), + ].join(':'); + + return getCachedResult(cacheKey, () => { + return getDateTimeFormatter(lang.code, lang.timeFormat, intlOptions).format(date); + }); +} + +function formatRelativeDateTime( + lang: LangFn, + targetDate: Date, + anchorDate: Date = new Date(), + type: RelativeType = 'numeric', + options?: Pick, +) { + const { maxRelativeDays } = options || {}; + const relativePart = getRelativePart(targetDate.getTime(), anchorDate.getTime(), maxRelativeDays); + if (!relativePart) { + return undefined; + } + + const cacheKey = [ + 'formatRelativeDateTime', + lang.code, + type, + targetDate.getTime() - anchorDate.getTime(), + maxRelativeDays, + relativePart.unit, + relativePart.value, + ].join(':'); + + return getCachedResult(cacheKey, () => { + return getRelativeTimeFormatter(lang.code, type).format(relativePart.value, relativePart.unit); + }); +} + +export function formatClockDuration(duration: number) { + const hours = Math.floor(duration / 3600); + const minutes = Math.floor((duration % 3600) / 60); + const seconds = Math.floor(duration % 3600 % 60); + + let string = ''; + if (hours > 0) { + string += `${String(hours)}:`; + string += `${String(minutes).padStart(2, '0')}:`; + } else { + string += `${String(minutes)}:`; + } + string += String(seconds).padStart(2, '0'); + + return string; +} + +function buildAbsoluteFormatterOptions(lang: LangFn, options: FormatDateTimeOptions) { + const dateStyle = options.date ?? false; + const timeStyle = options.time ?? false; + const formatterOptions: Intl.DateTimeFormatOptions = {}; + + if (options.weekday) { + formatterOptions.weekday = options.weekday === true ? 'long' : options.weekday; + } + + if (dateStyle) { + formatterOptions.month = dateStyle; + formatterOptions.day = options.includeDay === false ? undefined : 'numeric'; + formatterOptions.year = options.includeYear === false ? undefined : 'numeric'; + } + + if (timeStyle) { + formatterOptions.hour = '2-digit'; + formatterOptions.minute = '2-digit'; + formatterOptions.second = timeStyle === 'long' ? '2-digit' : undefined; + formatterOptions.hourCycle = getHourCycle(lang.timeFormat); + } + + if (!dateStyle && !timeStyle && !options.weekday) { + formatterOptions.month = 'numeric'; + formatterOptions.day = 'numeric'; + formatterOptions.year = 'numeric'; + } + + return formatterOptions; +} + +function getRelativePart(targetTime: number, anchorTime: number, maxRelativeDays?: number): RelativePart | undefined { + const diffInSeconds = Math.trunc((targetTime - anchorTime) / 1000); + const absDiffInSeconds = Math.abs(diffInSeconds); + if (maxRelativeDays && absDiffInSeconds >= maxRelativeDays * DAY_IN_SECONDS) { + return undefined; + } + + if (absDiffInSeconds < 60) { + return { unit: 'second' as const, value: diffInSeconds }; + } + + if (absDiffInSeconds < 60 * 60) { + return { unit: 'minute' as const, value: Math.trunc(diffInSeconds / 60) }; + } + + if (absDiffInSeconds < DAY_IN_SECONDS) { + return { unit: 'hour' as const, value: Math.trunc(diffInSeconds / (60 * 60)) }; + } + + return { unit: 'day' as const, value: Math.trunc(diffInSeconds / DAY_IN_SECONDS) }; +} + +function getDateTimeFormatter(locale: string, timeFormat: TimeFormat, options: Intl.DateTimeFormatOptions) { + const key = `dateTime:${locale}:${timeFormat}:${serializeRecord(options)}`; + const cachedFormatter = dateTimeFormatters.get(key); + if (cachedFormatter) { + return cachedFormatter; + } + + const formatter = createDateTimeFormatter(locale, timeFormat, options); + dateTimeFormatters.set(key, formatter); + return formatter; +} + +function createDateTimeFormatter(locale: string, timeFormat: TimeFormat, options: Intl.DateTimeFormatOptions) { + try { + return new Intl.DateTimeFormat(locale, { + ...options, + hourCycle: options.hour ? getHourCycle(timeFormat) : options.hourCycle, + }); + } catch { + return new Intl.DateTimeFormat(FALLBACK_LANG_CODE, { + ...options, + hourCycle: options.hour ? getHourCycle(timeFormat) : options.hourCycle, + }); + } +} + +function getRelativeTimeFormatter(locale: string, numericType: RelativeType) { + const key = `relative:${locale}:${numericType}`; + const cachedFormatter = relativeTimeFormatters.get(key); + if (cachedFormatter) { + return cachedFormatter; + } + + const formatter = createRelativeTimeFormatter(locale, numericType); + relativeTimeFormatters.set(key, formatter); + return formatter; +} + +function createRelativeTimeFormatter(locale: string, numericType: RelativeType) { + const numeric = numericType === 'numeric' ? 'always' : 'auto'; + try { + return new Intl.RelativeTimeFormat(locale, { numeric }); + } catch { + return new Intl.RelativeTimeFormat(FALLBACK_LANG_CODE, { numeric }); + } +} + +function getCachedResult(cacheKey: string, callback: () => string) { + const cachedResult = resultCache.get(cacheKey); + if (cachedResult !== undefined) { + return cachedResult; + } + + const newResult = callback(); + resultCache.set(cacheKey, newResult); + return newResult; +} + +function getHourCycle(timeFormat: TimeFormat) { + return timeFormat === '12h' ? 'h12' : 'h23'; +} + +function serializeRecord(record: object) { + return Object.entries(record as Record) + .filter(([, value]) => value !== undefined) + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, value]) => `${key}=${String(value)}`) + .join('&'); +} diff --git a/src/util/localization/index.ts b/src/util/localization/index.ts index 6034c8da8..087a4b997 100644 --- a/src/util/localization/index.ts +++ b/src/util/localization/index.ts @@ -6,6 +6,7 @@ import type { LangPack, LangPackStringValue, } from '../../api/types'; +import type { TimeFormat } from '../../types'; import type { LangKey, LangVariable } from '../../types/language'; import { type AdvancedLangFnOptions, @@ -22,7 +23,7 @@ import { type RegularLangFnParameters, } from './types'; -import { DEBUG, FORCE_FALLBACK_LANG, LANG_PACK } from '../../config'; +import { DEBUG, FALLBACK_LANG_CODE, FORCE_FALLBACK_LANG, LANG_PACK } from '../../config'; import { callApi } from '../../api/gramjs'; import renderText, { type TextFilter } from '../../components/common/helpers/renderText'; import { IS_INTL_LIST_FORMAT_SUPPORTED } from '../browser/globalEnvironment'; @@ -35,6 +36,7 @@ import { initialEstablishmentPromise, isCurrentTabMaster } from '../establishMul import { omit, unique } from '../iteratees'; import { replaceInStringsWithTeact } from '../replaceWithTeact'; import { fastRaf } from '../schedulers'; +import { resetDateFormatCache } from './dateFormat'; import Deferred from '../Deferred'; import LimitedMap from '../primitives/LimitedMap'; @@ -42,7 +44,7 @@ import LimitedMap from '../primitives/LimitedMap'; import initialStrings from '../../assets/localization/initialStrings'; const LANGPACK_STORE_PREFIX = 'langpack-'; -const FORMATTERS_FALLBACK_LANG = 'en'; +const FORMATTERS_FALLBACK_LANG = FALLBACK_LANG_CODE; const STRING_CACHE_LIMIT = 400; const TRANSLATION_CACHE = new LimitedMap(STRING_CACHE_LIMIT); @@ -52,6 +54,7 @@ let formatters: LangFormatters | undefined; let langPack: LangPack | undefined; let fallbackLangPack: LangPack | undefined; +let currentTimeFormat: TimeFormat = '24h'; let translationFn = createTranslationFn(); @@ -155,7 +158,7 @@ function updateLanguage(newLang: ApiLanguage) { function createFormatters() { if (!language) return; - const langCode = language.pluralCode; + const intlLocale = getIntlLocale(); const listFormatFallback = getBasicListFormat(); function createListFormat(lang: string, type: 'conjunction' | 'disjunction') { @@ -164,12 +167,12 @@ function createFormatters() { try { formatters = { - pluralRules: new Intl.PluralRules(langCode), - region: new Intl.DisplayNames(langCode, { type: 'region' }), - conjunction: createListFormat(langCode, 'conjunction'), - disjunction: createListFormat(langCode, 'disjunction'), - number: new Intl.NumberFormat(langCode), - preciseNumber: new Intl.NumberFormat(langCode, { + pluralRules: new Intl.PluralRules(intlLocale), + region: new Intl.DisplayNames(intlLocale, { type: 'region' }), + conjunction: createListFormat(intlLocale, 'conjunction'), + disjunction: createListFormat(intlLocale, 'disjunction'), + number: new Intl.NumberFormat(intlLocale), + preciseNumber: new Intl.NumberFormat(intlLocale, { minimumFractionDigits: 0, maximumFractionDigits: 10, }), @@ -189,6 +192,8 @@ function createFormatters() { }), }; } + + resetDateFormatCache(); } function updateLangPack(newLangPack: LangPack) { @@ -317,6 +322,7 @@ function createTranslationFn(): LangFn { fn.rawCode = language?.langCode || FORMATTERS_FALLBACK_LANG; fn.isRtl = language?.isRtl; fn.code = language?.pluralCode || FORMATTERS_FALLBACK_LANG; + fn.timeFormat = currentTimeFormat; fn.with = ({ key, variables, options }: LangFnParameters) => { if (options && areAdvancedLangFnOptions(options)) { return processTranslationAdvanced(key, variables as Record, options); @@ -343,8 +349,24 @@ export function getTranslationFn(): LangFn { return translationFn; } +export function setTimeFormat(timeFormat: TimeFormat) { + if (timeFormat === currentTimeFormat) { + return; + } + + currentTimeFormat = timeFormat; + resetDateFormatCache(); + translationFn.timeFormat = currentTimeFormat; + scheduleCallbacks(); +} + +function getIntlLocale(languageInfo = language) { + return languageInfo?.pluralCode || FORMATTERS_FALLBACK_LANG; +} + function getString(langKey: LangKey, count: number) { - let langPackStringValue = !FORCE_FALLBACK_LANG ? langPack?.strings[langKey] : undefined; + const shouldForceFallback = FORCE_FALLBACK_LANG && language?.langCode === FALLBACK_LANG_CODE; + let langPackStringValue = !shouldForceFallback ? langPack?.strings[langKey] : undefined; if (!langPackStringValue && !fallbackLangPack) { loadFallbackPack(); diff --git a/src/util/localization/types.ts b/src/util/localization/types.ts index 1f41cebdb..49ec92827 100644 --- a/src/util/localization/types.ts +++ b/src/util/localization/types.ts @@ -8,6 +8,7 @@ import type { LangPackStringValueRegular, } from '../../api/types'; import type { TextFilter } from '../../components/common/helpers/renderText'; +import type { TimeFormat } from '../../types'; import type { LangPairPluralWithVariables, LangPairWithVariables, @@ -164,6 +165,7 @@ export type LangFn = { disjunction: (list: string[]) => string; number: (value: number) => string; preciseNumber: (value: number) => string; + timeFormat: TimeFormat; internalFormatters: LangFormatters; isRtl?: boolean; rawCode: string; diff --git a/src/util/oldLangProvider.ts b/src/util/oldLangProvider.ts index 2e9c39ac1..c335847c0 100644 --- a/src/util/oldLangProvider.ts +++ b/src/util/oldLangProvider.ts @@ -4,6 +4,7 @@ import type { ApiOldLangPack, ApiOldLangString } from '../api/types'; import type { LangCode, TimeFormat } from '../types'; import { + FALLBACK_LANG_CODE, LANG_CACHE_NAME, LANG_PACKS, } from '../config'; import { selectSharedSettings } from '../global/selectors/sharedState'; @@ -214,7 +215,7 @@ async function fetchRemote(langCode: string): Promise