diff --git a/src/api/gramjs/apiBuilders/messages.ts b/src/api/gramjs/apiBuilders/messages.ts index c08988166..f54a82473 100644 --- a/src/api/gramjs/apiBuilders/messages.ts +++ b/src/api/gramjs/apiBuilders/messages.ts @@ -273,7 +273,7 @@ function buildApiMessageForwardInfo(fwdFrom: GramJs.MessageFwdHeader, isChatWith isLinkedChannelPost: Boolean(fwdFrom.channelPost && savedFromPeerId && !isChatWithSelf), savedFromPeerId, fromId, - fromChatId: savedFromPeerId || fromId, + fromChatId: fromId || savedFromPeerId, fromMessageId: fwdFrom.savedFromMsgId || fwdFrom.channelPost, hiddenUserName: fwdFrom.fromName, postAuthorTitle: fwdFrom.postAuthor, diff --git a/src/components/common/Avatar.scss b/src/components/common/Avatar.scss index 031ce5cfa..2033b4621 100644 --- a/src/components/common/Avatar.scss +++ b/src/components/common/Avatar.scss @@ -249,4 +249,8 @@ &.forum { --radius: var(--border-radius-forum-avatar); } + + &.hidden-user { + --color-user: var(--color-deleted-account); + } } diff --git a/src/components/common/Avatar.tsx b/src/components/common/Avatar.tsx index 9ad840c29..e70e9af50 100644 --- a/src/components/common/Avatar.tsx +++ b/src/components/common/Avatar.tsx @@ -211,6 +211,7 @@ const Avatar: FC = ({ `Avatar size-${size}`, className, getPeerColorClass(peer), + !peer && text && 'hidden-user', isSavedMessages && 'saved-messages', isAnonymousForwards && 'anonymous-forwards', isDeleted && 'deleted-account', diff --git a/src/components/middle/hooks/useAuthorWidth.ts b/src/components/middle/hooks/useAuthorWidth.ts deleted file mode 100644 index e5ffd018d..000000000 --- a/src/components/middle/hooks/useAuthorWidth.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { RefObject } from 'react'; -import { useLayoutEffect } from '../../../lib/teact/teact'; - -import { requestForcedReflow } from '../../../lib/fasterdom/fasterdom'; - -export default function useAuthorWidth( - containerRef: RefObject, - signature?: string, -) { - useLayoutEffect(() => { - if (!signature) return; - - requestForcedReflow(() => { - const width = containerRef.current!.querySelector('.message-signature')?.offsetWidth; - if (!width) return undefined; - - return () => { - containerRef.current!.style.setProperty('--meta-safe-author-width', `${width}px`); - }; - }); - }, [containerRef, signature]); -} diff --git a/src/components/middle/message/Message.scss b/src/components/middle/message/Message.scss index 9642f747d..9b5e6b196 100644 --- a/src/components/middle/message/Message.scss +++ b/src/components/middle/message/Message.scss @@ -20,12 +20,6 @@ --accent-color: var(--color-primary); --accent-shade-color: var(--color-primary-shade); --secondary-color: var(--color-text-secondary); - --meta-safe-area-base: 2.25rem; - --meta-safe-author-width: 0px; - --meta-safe-area-extra-width: 0px; - --meta-safe-area-size: calc( - var(--meta-safe-area-base) + var(--meta-safe-author-width) + var(--meta-safe-area-extra-width) - ); --color-voice-transcribe: var(--color-voice-transcribe-button); --thumbs-background: var(--color-background); --deleting-translate-x: -50%; @@ -200,7 +194,6 @@ --color-code: var(--color-code-own); --color-code-bg: var(--color-code-own-bg); --color-links: var(--color-own-links); - --meta-safe-area-base: 3.5rem; --deleting-translate-x: 50%; --color-text-green: var(--color-accent-own); --color-voice-transcribe: var(--color-voice-transcribe-button-own); @@ -336,26 +329,6 @@ } } - &.has-views { - --meta-safe-area-extra-width: 4rem; - } - - &.was-edited { - --meta-safe-area-extra-width: 2.5rem; - - &.has-views { - --meta-safe-area-extra-width: 7.5rem; - } - - html[lang="ru"] & { - --meta-safe-area-extra-width: 3.5rem; - - &.has-views { - --meta-safe-area-extra-width: 8.5rem; - } - } - } - .select-mode-active & { cursor: var(--custom-cursor, pointer); diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index d38f94185..a6c32ef23 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -34,7 +34,6 @@ import { AudioOrigin } from '../../../types'; import { EMOJI_STATUS_LOOP_LIMIT, GENERAL_TOPIC_ID } from '../../../config'; import { areReactionsEmpty, - getIsSavedDialog, getMessageContent, getMessageCustomShape, getMessageHtmlId, @@ -129,7 +128,6 @@ import useResizeObserver from '../../../hooks/useResizeObserver'; import useShowTransition from '../../../hooks/useShowTransition'; import useTextLanguage from '../../../hooks/useTextLanguage'; import useThrottledCallback from '../../../hooks/useThrottledCallback'; -import useAuthorWidth from '../hooks/useAuthorWidth'; import useDetectChatLanguage from './hooks/useDetectChatLanguage'; import useFocusMessage from './hooks/useFocusMessage'; import useInnerHandlers from './hooks/useInnerHandlers'; @@ -279,7 +277,6 @@ type StateProps = { isConnected: boolean; isLoadingComments?: boolean; shouldWarnAboutSvg?: boolean; - isInSavedDialog?: boolean; }; type MetaPosition = @@ -394,7 +391,6 @@ const Message: FC = ({ isConnected, getIsMessageListReady, shouldWarnAboutSvg, - isInSavedDialog, onPinnedIntersectionChange, }) => { const { @@ -749,9 +745,8 @@ const Message: FC = ({ ); const signature = (isChannel && message.postAuthorTitle) - || (!asForwarded && forwardInfo?.postAuthorTitle) + || ((asForwarded || isChatWithSelf) && forwardInfo?.postAuthorTitle) || undefined; - useAuthorWidth(ref, signature); const shouldFocusOnResize = isLastInList; @@ -924,7 +919,7 @@ const Message: FC = ({ ( const hasActiveReactions = Boolean(reactionMessage && activeReactions[getMessageKey(reactionMessage)]?.length); - const isInSavedDialog = getIsSavedDialog(chatId, threadId, global.currentUserId); - return { theme: selectTheme(global), forceSenderName, @@ -1637,7 +1630,6 @@ export default memo(withGlobal( withStickerEffects: selectPerformanceSettingsValue(global, 'stickerEffects'), webPageStory, isConnected, - isInSavedDialog, isLoadingComments: repliesThreadInfo?.isCommentsInfo && loadingThread?.loadingChatId === repliesThreadInfo?.originChannelId && loadingThread?.loadingMessageId === repliesThreadInfo?.originMessageId, diff --git a/src/components/middle/message/MessageMeta.scss b/src/components/middle/message/MessageMeta.scss index dcdd5505c..4d2003872 100644 --- a/src/components/middle/message/MessageMeta.scss +++ b/src/components/middle/message/MessageMeta.scss @@ -10,7 +10,7 @@ padding: 0 0.25rem; color: white; cursor: var(--custom-cursor, pointer); - max-width: 100%; + max-width: calc(100% - 0.5rem); user-select: none; .message-time, @@ -67,8 +67,6 @@ margin-left: 0.125rem; margin-right: 0.375rem; font-size: 1.125rem; - position: relative; - top: -0.0625rem; } .icon-reply-filled { @@ -132,6 +130,7 @@ .is-forwarded.media:not(.text) & { bottom: 0.9375rem; right: 0.8125rem; + max-width: calc(100% - 2.25rem); } .Message.own .has-solid-background & { @@ -142,6 +141,7 @@ margin-left: -0.1875rem; font-size: 1.1875rem; border-radius: 0.625rem; + flex-shrink: 0; .Message.own & { color: var(--color-accent-own); diff --git a/src/components/middle/message/MessageMeta.tsx b/src/components/middle/message/MessageMeta.tsx index d45c06aa1..92703fb7b 100644 --- a/src/components/middle/message/MessageMeta.tsx +++ b/src/components/middle/message/MessageMeta.tsx @@ -7,7 +7,7 @@ import type { } from '../../../api/types'; import buildClassName from '../../../util/buildClassName'; -import { formatDateTimeToString, formatTime } from '../../../util/dateFormat'; +import { formatDateTimeToString, formatPastTimeShort, formatTime } from '../../../util/dateFormat'; import { formatIntegerCompact } from '../../../util/textFormat'; import renderText from '../../common/helpers/renderText'; @@ -29,7 +29,7 @@ type OwnProps = { repliesThreadInfo?: ApiThreadInfo; isTranslated?: boolean; isPinned?: boolean; - isInSavedDialog?: boolean; + withFullDate?: boolean; onClick: (e: React.MouseEvent) => void; onTranslationClick: (e: React.MouseEvent) => void; renderQuickReactionButton?: () => TeactNode | undefined; @@ -46,7 +46,7 @@ const MessageMeta: FC = ({ noReplies, isTranslated, isPinned, - isInSavedDialog, + withFullDate, onClick, onTranslationClick, onOpenThread, @@ -96,6 +96,15 @@ const MessageMeta: FC = ({ // eslint-disable-next-line react-hooks-static-deps/exhaustive-deps }, [isActivated, lang, message, lang.timeFormat]); + const date = useMemo(() => { + const time = formatTime(lang, message.date * 1000); + if (!withFullDate) { + return time; + } + + return formatPastTimeShort(lang, (message.forwardInfo?.date || message.date) * 1000, true); + }, [lang, message.date, message.forwardInfo?.date, withFullDate]); + const fullClassName = buildClassName( 'MessageMeta', withReactionOffset && 'reactions-offset', @@ -144,9 +153,7 @@ const MessageMeta: FC = ({ )} {message.isEdited && `${lang('EditedMessage')} `} - {isInSavedDialog - ? formatDateTimeToString((message.forwardInfo?.date || message.date) * 1000, lang.code, true) - : formatTime(lang, message.date * 1000)} + {date} {outgoingStatus && ( diff --git a/src/components/middle/message/WebPage.scss b/src/components/middle/message/WebPage.scss index 08a1c1d41..de8b55453 100644 --- a/src/components/middle/message/WebPage.scss +++ b/src/components/middle/message/WebPage.scss @@ -102,7 +102,7 @@ } .message-content:not(.has-reactions) & { - margin-bottom: calc(var(--message-meta-height) + 0.375rem) !important; + margin-bottom: calc(var(--message-meta-height)) !important; } &.with-square-photo .WebPage--content { diff --git a/src/components/middle/message/_message-content.scss b/src/components/middle/message/_message-content.scss index f2e1923f3..b79d7cb23 100644 --- a/src/components/middle/message/_message-content.scss +++ b/src/components/middle/message/_message-content.scss @@ -364,13 +364,6 @@ &.has-solid-background { padding: 0.3125rem 0.5rem 0.375rem; - - .forwarded-message > .text-content:not(.with-meta):last-child::after { - content: ""; - display: inline-block; - width: var(--meta-safe-area-size); - height: 1rem; - } } body.is-ios &.has-solid-background { diff --git a/src/config.ts b/src/config.ts index 289c69355..ddc9135bb 100644 --- a/src/config.ts +++ b/src/config.ts @@ -51,7 +51,7 @@ export const CUSTOM_EMOJI_PREVIEW_CACHE_DISABLED = false; export const CUSTOM_EMOJI_PREVIEW_CACHE_NAME = 'tt-custom-emoji-preview'; export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg'; -export const LANG_CACHE_NAME = 'tt-lang-packs-v30'; +export const LANG_CACHE_NAME = 'tt-lang-packs-v31'; export const ASSET_CACHE_NAME = 'tt-assets'; export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500]; export const DATA_BROADCAST_CHANNEL_NAME = 'tt-global'; diff --git a/src/util/dateFormat.ts b/src/util/dateFormat.ts index 2ad7f67bd..1dc5970d5 100644 --- a/src/util/dateFormat.ts +++ b/src/util/dateFormat.ts @@ -53,23 +53,27 @@ export function formatTime(lang: LangFn, datetime: number | Date) { return `${String(hours).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}${marker}`; } -export function formatPastTimeShort(lang: LangFn, datetime: number | Date) { +export function formatPastTimeShort(lang: LangFn, datetime: number | Date, alwaysShowTime = false) { const date = typeof datetime === 'number' ? new Date(datetime) : datetime; + const time = formatTime(lang, date); + const today = getDayStart(new Date()); if (date >= today) { - return formatTime(lang, date); + return time; } const weekAgo = new Date(today); weekAgo.setDate(today.getDate() - 7); if (date >= weekAgo) { - return lang(`Weekday.Short${WEEKDAYS_FULL[date.getDay()]}`); + const weekday = lang(`Weekday.Short${WEEKDAYS_FULL[date.getDay()]}`); + return alwaysShowTime ? lang('FullDateTimeFormat', [weekday, time]) : weekday; } const noYear = date.getFullYear() === today.getFullYear(); - return formatDateToString(date, lang.code, noYear); + const formattedDate = formatDateToString(date, lang.code, noYear); + return alwaysShowTime ? lang('FullDateTimeFormat', [formattedDate, time]) : formattedDate; } export function formatFullDate(lang: LangFn, datetime: number | Date) { diff --git a/src/util/fallbackLangPack.ts b/src/util/fallbackLangPack.ts index 99a4fd630..7365cdfc5 100644 --- a/src/util/fallbackLangPack.ts +++ b/src/util/fallbackLangPack.ts @@ -509,4 +509,5 @@ export default { 'Video.Unsupported.Mobile': 'Unfortunately, this video can\'t be played on Telegram Web. Try opening it with our **mobile app** instead.', SlowModeWait: 'Slow Mode — %d', OpenMapWith: 'Open map with...', + FullDateTimeFormat: '%@, %@', } as ApiLangPack;