Message: Show forward counter on view hover (#5447)

This commit is contained in:
zubiden 2025-01-21 18:20:54 +01:00 committed by Alexander Zinchuk
parent 9b57bd9e21
commit 5381c148e4
5 changed files with 82 additions and 19 deletions

View File

@ -468,6 +468,13 @@ export function updater(update: Update) {
id: update.id,
message: { viewsCount: update.views },
});
} else if (update instanceof GramJs.UpdateChannelMessageForwards) {
sendApiUpdate({
'@type': 'updateMessage',
chatId: buildApiPeerId(update.channelId, 'channel'),
id: update.id,
message: { forwardsCount: update.forwards },
});
// Chats
} else if (update instanceof GramJs.UpdateReadHistoryInbox) {

View File

@ -732,6 +732,18 @@
"Reminders" = "Reminders";
"Messages_one" = "{count} message";
"Messages_other" = "{count} messages";
"MessageTooltipForwards_one" = "Shares: {count}";
"MessageTooltipForwards_other" = "Shares: {count}";
"MessageTooltipViews_one" = "Views: {count}";
"MessageTooltipViews_other" = "Views: {count}";
"MessageTooltipReplies_one" = "Replies: {count}";
"MessageTooltipReplies_other" = "Replies: {count}";
"MessageTooltipEditedDate" = "Edited: {date}";
"MessageTooltipForwardedDate" = "Original: {date}";
"MessageMetaEdited" = "edited";
"MessageMetaApproximate" = "approx.";
"MessageMetaImported" = "imported";
"ImportedInfo" = "This message was imported from another app. We can't guarantee it's real.";
"ScheduledMessagesEmptyPlaceholder" = "No scheduled messages here yet...";
"ConversationCloudStorageInfoTitle" = "Your Cloud Storage";
"ConversationClousStorageInfoDescription1" = "• Forward messages here to save them";

View File

@ -74,12 +74,14 @@
margin-left: 0.125rem;
margin-right: 0.375rem;
font-size: 1.125rem;
line-height: inherit;
}
.icon-reply-filled {
margin-left: 0.125rem;
margin-right: 0.375rem;
font-size: 0.75rem;
line-height: inherit;
}
.has-solid-background & {

View File

@ -12,6 +12,7 @@ import { formatIntegerCompact } from '../../../util/textFormat';
import renderText from '../../common/helpers/renderText';
import useFlag from '../../../hooks/useFlag';
import useLang from '../../../hooks/useLang';
import useOldLang from '../../../hooks/useOldLang';
import AnimatedCounter from '../../common/AnimatedCounter';
@ -57,14 +58,19 @@ const MessageMeta: FC<OwnProps> = ({
onOpenThread,
}) => {
const { showNotification } = getActions();
const lang = useOldLang();
const [isActivated, markActivated] = useFlag();
const oldLang = useOldLang();
const lang = useLang();
function handleImportedClick(e: React.MouseEvent) {
e.stopPropagation();
showNotification({
message: lang('ImportedInfo'),
message: {
key: 'ImportedInfo',
},
});
}
@ -73,42 +79,59 @@ const MessageMeta: FC<OwnProps> = ({
onOpenThread();
}
const title = useMemo(() => {
const dateTitle = useMemo(() => {
if (!isActivated) return undefined;
const createDateTime = formatDateTimeToString(message.date * 1000, lang.code, undefined, lang.timeFormat);
const createDateTime = formatDateTimeToString(message.date * 1000, oldLang.code, undefined, oldLang.timeFormat);
const editDateTime = message.isEdited
&& formatDateTimeToString(message.editDate! * 1000, lang.code, undefined, lang.timeFormat);
&& formatDateTimeToString(message.editDate! * 1000, oldLang.code, undefined, oldLang.timeFormat);
const forwardedDateTime = message.forwardInfo
&& formatDateTimeToString(
(message.forwardInfo.savedDate || message.forwardInfo.date) * 1000,
lang.code,
oldLang.code,
undefined,
lang.timeFormat,
oldLang.timeFormat,
);
let text = createDateTime;
if (editDateTime) {
text += '\n';
text += lang('lng_edited_date').replace('{date}', editDateTime);
text += lang('MessageTooltipEditedDate', { date: editDateTime });
}
if (forwardedDateTime) {
text += '\n';
text += lang('lng_forwarded_date').replace('{date}', forwardedDateTime);
text += lang('MessageTooltipForwardedDate', { date: forwardedDateTime });
}
return text;
// We need to listen to timeformat change
// eslint-disable-next-line react-hooks-static-deps/exhaustive-deps
}, [isActivated, lang, message, lang.timeFormat]);
}, [isActivated, oldLang, message, oldLang.timeFormat]);
const viewsTitle = useMemo(() => {
if (!message.viewsCount) return undefined;
let text = lang('MessageTooltipViews', { count: message.viewsCount }, { pluralValue: message.viewsCount });
if (message.forwardsCount) {
text += '\n';
text += lang('MessageTooltipForwards', { count: message.forwardsCount }, { pluralValue: message.forwardsCount });
}
return text;
}, [lang, message.forwardsCount, message.viewsCount]);
const repliesTitle = useMemo(() => {
const count = repliesThreadInfo?.messagesCount;
if (!count) return undefined;
return lang('MessageTooltipReplies', { count }, { pluralValue: count });
}, [lang, repliesThreadInfo]);
const date = useMemo(() => {
const time = formatTime(lang, message.date * 1000);
const time = formatTime(oldLang, message.date * 1000);
if (!withFullDate) {
return time;
}
return formatPastTimeShort(lang, (message.forwardInfo?.date || message.date) * 1000, true);
}, [lang, message.date, message.forwardInfo?.date, withFullDate]);
return formatPastTimeShort(oldLang, (message.forwardInfo?.date || message.date) * 1000, true);
}, [oldLang, message.date, message.forwardInfo?.date, withFullDate]);
const fullClassName = buildClassName(
'MessageMeta',
@ -133,14 +156,14 @@ const MessageMeta: FC<OwnProps> = ({
)}
{Boolean(message.viewsCount) && (
<>
<span className="message-views">
<span className="message-views" title={viewsTitle}>
{formatIntegerCompact(message.viewsCount!)}
</span>
<Icon name="channelviews" />
</>
)}
{!noReplies && Boolean(repliesThreadInfo?.messagesCount) && (
<span onClick={handleOpenThread} className="message-replies-wrapper">
<span onClick={handleOpenThread} className="message-replies-wrapper" title={repliesTitle}>
<span className="message-replies">
<AnimatedCounter text={formatIntegerCompact(repliesThreadInfo!.messagesCount!)} />
</span>
@ -153,17 +176,17 @@ const MessageMeta: FC<OwnProps> = ({
{signature && (
<span className="message-signature">{renderText(signature)}</span>
)}
<span className="message-time" title={title} onMouseEnter={markActivated}>
<span className="message-time" title={dateTitle} onMouseEnter={markActivated}>
{message.forwardInfo?.isImported && (
<>
<span className="message-imported" onClick={handleImportedClick}>
{formatDateTimeToString(message.forwardInfo.date * 1000, lang.code, true)}
</span>
<span className="message-imported" onClick={handleImportedClick}>{lang('ImportedMessage')}</span>
<span className="message-imported" onClick={handleImportedClick}>{lang('MessageMetaImported')}</span>
</>
)}
{message.isEdited && `${lang('EditedMessage')} `}
{message.isVideoProcessingPending && `${lang('lng_approximate')} `}
{message.isEdited && `${lang('MessageMetaEdited')} `}
{message.isVideoProcessingPending && `${lang('MessageMetaApproximate')} `}
{date}
</span>
{outgoingStatus && (

View File

@ -627,6 +627,10 @@ export interface LangPair {
'ContextCopySelectedItems': undefined;
'EditAdminGroupDeleteMessages': undefined;
'Reminders': undefined;
'MessageMetaEdited': undefined;
'MessageMetaApproximate': undefined;
'MessageMetaImported': undefined;
'ImportedInfo': undefined;
'ScheduledMessagesEmptyPlaceholder': undefined;
'ConversationCloudStorageInfoTitle': undefined;
'ConversationClousStorageInfoDescription1': undefined;
@ -1396,6 +1400,12 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'MessageScheduledOn': {
'date': V;
};
'MessageTooltipEditedDate': {
'date': V;
};
'MessageTooltipForwardedDate': {
'date': V;
};
'EmptyGroupInfoLine1': {
'count': V;
};
@ -1761,6 +1771,15 @@ export interface LangPairPluralWithVariables<V extends unknown = LangVariable> {
'Messages': {
'count': V;
};
'MessageTooltipForwards': {
'count': V;
};
'MessageTooltipViews': {
'count': V;
};
'MessageTooltipReplies': {
'count': V;
};
'Hours': {
'count': V;
};