Message: Display formatted dates (#6795)
This commit is contained in:
parent
bc7468265d
commit
b98f790308
@ -286,6 +286,21 @@ export function buildApiMessageEntity(entity: GramJs.TypeMessageEntity): ApiMess
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity instanceof GramJs.MessageEntityFormattedDate) {
|
||||||
|
return {
|
||||||
|
type: ApiMessageEntityTypes.FormattedDate,
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
date: entity.date,
|
||||||
|
relative: entity.relative,
|
||||||
|
shortTime: entity.shortTime,
|
||||||
|
longTime: entity.longTime,
|
||||||
|
shortDate: entity.shortDate,
|
||||||
|
longDate: entity.longDate,
|
||||||
|
dayOfWeek: entity.dayOfWeek,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: type as `${ApiMessageEntityDefault['type']}`,
|
type: type as `${ApiMessageEntityDefault['type']}`,
|
||||||
offset,
|
offset,
|
||||||
|
|||||||
@ -420,6 +420,18 @@ export function buildMtpMessageEntity(entity: ApiMessageEntity): GramJs.TypeMess
|
|||||||
return new GramJs.MessageEntitySpoiler({ offset, length });
|
return new GramJs.MessageEntitySpoiler({ offset, length });
|
||||||
case ApiMessageEntityTypes.CustomEmoji:
|
case ApiMessageEntityTypes.CustomEmoji:
|
||||||
return new GramJs.MessageEntityCustomEmoji({ offset, length, documentId: BigInt(entity.documentId) });
|
return new GramJs.MessageEntityCustomEmoji({ offset, length, documentId: BigInt(entity.documentId) });
|
||||||
|
case ApiMessageEntityTypes.FormattedDate:
|
||||||
|
return new GramJs.MessageEntityFormattedDate({
|
||||||
|
offset,
|
||||||
|
length,
|
||||||
|
date: entity.date,
|
||||||
|
relative: entity.relative,
|
||||||
|
shortTime: entity.shortTime,
|
||||||
|
longTime: entity.longTime,
|
||||||
|
shortDate: entity.shortDate,
|
||||||
|
longDate: entity.longDate,
|
||||||
|
dayOfWeek: entity.dayOfWeek,
|
||||||
|
});
|
||||||
default:
|
default:
|
||||||
return new GramJs.MessageEntityUnknown({ offset, length });
|
return new GramJs.MessageEntityUnknown({ offset, length });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -509,7 +509,8 @@ export type ApiMessageEntityDefault = {
|
|||||||
type: Exclude<
|
type: Exclude<
|
||||||
`${ApiMessageEntityTypes}`,
|
`${ApiMessageEntityTypes}`,
|
||||||
`${ApiMessageEntityTypes.Pre}` | `${ApiMessageEntityTypes.TextUrl}` | `${ApiMessageEntityTypes.MentionName}` |
|
`${ApiMessageEntityTypes.Pre}` | `${ApiMessageEntityTypes.TextUrl}` | `${ApiMessageEntityTypes.MentionName}` |
|
||||||
`${ApiMessageEntityTypes.Blockquote}` | `${ApiMessageEntityTypes.CustomEmoji}` | `${ApiMessageEntityTypes.Timestamp}`
|
`${ApiMessageEntityTypes.Blockquote}` | `${ApiMessageEntityTypes.CustomEmoji}` |
|
||||||
|
`${ApiMessageEntityTypes.Timestamp}` | `${ApiMessageEntityTypes.FormattedDate}`
|
||||||
>;
|
>;
|
||||||
offset: number;
|
offset: number;
|
||||||
length: number;
|
length: number;
|
||||||
@ -550,6 +551,19 @@ export type ApiMessageEntityCustomEmoji = {
|
|||||||
documentId: string;
|
documentId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ApiMessageEntityFormattedDate = {
|
||||||
|
type: ApiMessageEntityTypes.FormattedDate;
|
||||||
|
offset: number;
|
||||||
|
length: number;
|
||||||
|
date: number;
|
||||||
|
relative?: true;
|
||||||
|
shortTime?: true;
|
||||||
|
longTime?: true;
|
||||||
|
shortDate?: true;
|
||||||
|
longDate?: true;
|
||||||
|
dayOfWeek?: true;
|
||||||
|
};
|
||||||
|
|
||||||
// Local entities
|
// Local entities
|
||||||
export type ApiMessageEntityTimestamp = {
|
export type ApiMessageEntityTimestamp = {
|
||||||
type: ApiMessageEntityTypes.Timestamp;
|
type: ApiMessageEntityTypes.Timestamp;
|
||||||
@ -559,7 +573,8 @@ export type ApiMessageEntityTimestamp = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ApiMessageEntity = ApiMessageEntityDefault | ApiMessageEntityPre | ApiMessageEntityTextUrl |
|
export type ApiMessageEntity = ApiMessageEntityDefault | ApiMessageEntityPre | ApiMessageEntityTextUrl |
|
||||||
ApiMessageEntityMentionName | ApiMessageEntityCustomEmoji | ApiMessageEntityBlockquote | ApiMessageEntityTimestamp;
|
ApiMessageEntityMentionName | ApiMessageEntityCustomEmoji | ApiMessageEntityBlockquote | ApiMessageEntityTimestamp |
|
||||||
|
ApiMessageEntityFormattedDate;
|
||||||
|
|
||||||
export enum ApiMessageEntityTypes {
|
export enum ApiMessageEntityTypes {
|
||||||
Bold = 'MessageEntityBold',
|
Bold = 'MessageEntityBold',
|
||||||
@ -582,6 +597,7 @@ export enum ApiMessageEntityTypes {
|
|||||||
CustomEmoji = 'MessageEntityCustomEmoji',
|
CustomEmoji = 'MessageEntityCustomEmoji',
|
||||||
Timestamp = 'MessageEntityTimestamp',
|
Timestamp = 'MessageEntityTimestamp',
|
||||||
QuoteFocus = 'MessageEntityQuoteFocus',
|
QuoteFocus = 'MessageEntityQuoteFocus',
|
||||||
|
FormattedDate = 'MessageEntityFormattedDate',
|
||||||
Unknown = 'MessageEntityUnknown',
|
Unknown = 'MessageEntityUnknown',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2772,5 +2772,8 @@
|
|||||||
"RankEditTextOwn" = "Share your role, title or how you're known in this group. Your tag is visible to all members.";
|
"RankEditTextOwn" = "Share your role, title or how you're known in this group. Your tag is visible to all members.";
|
||||||
"RankEditText" = "Add a short tag next to {user}'s name.";
|
"RankEditText" = "Add a short tag next to {user}'s name.";
|
||||||
"MenuAddCaption" = "Add Caption";
|
"MenuAddCaption" = "Add Caption";
|
||||||
|
"MenuCopyDate" = "Copy Date";
|
||||||
|
"DateCopiedToast" = "Date copied to clipboard";
|
||||||
|
"ReminderSetToast" = "You set up a reminder in **Saved Messages**";
|
||||||
"NoForwardsRequestReject" = "Reject";
|
"NoForwardsRequestReject" = "Reject";
|
||||||
"NoForwardsRequestAccept" = "Accept";
|
"NoForwardsRequestAccept" = "Accept";
|
||||||
|
|||||||
@ -1265,7 +1265,6 @@ const Composer = ({
|
|||||||
effectId,
|
effectId,
|
||||||
webPageMediaSize: attachmentSettings.webPageMediaSize,
|
webPageMediaSize: attachmentSettings.webPageMediaSize,
|
||||||
webPageUrl: hasWebPagePreview ? webPagePreview.url : undefined,
|
webPageUrl: hasWebPagePreview ? webPagePreview.url : undefined,
|
||||||
isForwarding,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
177
src/components/common/FormattedDate.tsx
Normal file
177
src/components/common/FormattedDate.tsx
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import { type TeactNode, useMemo, useRef, useState } from '@teact';
|
||||||
|
import { getActions } from '../../global';
|
||||||
|
|
||||||
|
import { type ApiMessageEntityFormattedDate, ApiMessageEntityTypes } from '../../api/types';
|
||||||
|
|
||||||
|
import { copyTextToClipboard } from '../../util/clipboard';
|
||||||
|
import { formatDateTime, secondsToDate } from '../../util/localization/dateFormat';
|
||||||
|
import { getServerTime } from '../../util/serverTime';
|
||||||
|
|
||||||
|
import useInterval from '../../hooks/schedulers/useInterval';
|
||||||
|
import useContextMenuHandlers from '../../hooks/useContextMenuHandlers';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
|
import useSchedule from '../../hooks/useSchedule';
|
||||||
|
|
||||||
|
import Menu from '../ui/Menu';
|
||||||
|
import MenuItem from '../ui/MenuItem';
|
||||||
|
|
||||||
|
type OwnProps = {
|
||||||
|
children?: TeactNode;
|
||||||
|
entity: ApiMessageEntityFormattedDate;
|
||||||
|
asPreview?: boolean;
|
||||||
|
chatId?: string;
|
||||||
|
messageId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const FormattedDate = ({
|
||||||
|
children,
|
||||||
|
chatId,
|
||||||
|
messageId,
|
||||||
|
entity,
|
||||||
|
asPreview,
|
||||||
|
}: OwnProps) => {
|
||||||
|
const { showNotification, openForwardMenu, forwardToSavedMessages } = getActions();
|
||||||
|
const [cacheBreaker, setCacheBreaker] = useState(0);
|
||||||
|
|
||||||
|
const ref = useRef<HTMLAnchorElement>();
|
||||||
|
const menuRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
const [requestCalendar, calendar] = useSchedule(undefined, undefined, entity.date);
|
||||||
|
|
||||||
|
useInterval(
|
||||||
|
() => setCacheBreaker((prev) => prev + 1),
|
||||||
|
getUpdateInterval(Math.abs(entity.date - getServerTime())),
|
||||||
|
);
|
||||||
|
|
||||||
|
const canSetReminder = Boolean(chatId && messageId);
|
||||||
|
|
||||||
|
const { formattedDate, canonicalDate } = useMemo(() => {
|
||||||
|
void cacheBreaker;
|
||||||
|
|
||||||
|
const { type, offset, length, date, ...formatOptions } = entity;
|
||||||
|
const canonical = formatDateTime(lang, secondsToDate(date), {
|
||||||
|
date: 'long',
|
||||||
|
includeYear: true,
|
||||||
|
includeDay: true,
|
||||||
|
time: 'long',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.values(formatOptions).every((value) => value === undefined)) {
|
||||||
|
return { formattedDate: undefined, canonicalDate: canonical };
|
||||||
|
}
|
||||||
|
|
||||||
|
const { relative, shortTime, longTime, shortDate, longDate, dayOfWeek } = formatOptions;
|
||||||
|
|
||||||
|
const formatted = formatDateTime(lang, secondsToDate(date), {
|
||||||
|
relative: relative ? 'auto' : undefined,
|
||||||
|
time: shortTime ? 'short' : longTime ? 'long' : undefined,
|
||||||
|
date: shortDate ? 'short' : longDate ? 'long' : undefined,
|
||||||
|
weekday: dayOfWeek ? 'long' : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
return { formattedDate: formatted, canonicalDate: canonical };
|
||||||
|
}, [lang, entity, cacheBreaker]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
isContextMenuOpen,
|
||||||
|
contextMenuAnchor,
|
||||||
|
handleContextMenu,
|
||||||
|
handleContextMenuClose,
|
||||||
|
handleContextMenuHide,
|
||||||
|
} = useContextMenuHandlers(ref, asPreview);
|
||||||
|
|
||||||
|
const getTriggerElement = useLastCallback(() => ref.current);
|
||||||
|
const getRootElement = useLastCallback(() => document.body);
|
||||||
|
const getMenuElement = useLastCallback(() => menuRef.current);
|
||||||
|
const getLayout = useLastCallback(() => ({ withPortal: true }));
|
||||||
|
|
||||||
|
const handleCopy = useLastCallback(() => {
|
||||||
|
copyTextToClipboard(canonicalDate);
|
||||||
|
showNotification({ message: lang('DateCopiedToast') });
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSetReminder = useLastCallback(() => {
|
||||||
|
if (!chatId || !messageId) return;
|
||||||
|
requestCalendar((scheduledAt) => {
|
||||||
|
openForwardMenu({ fromChatId: chatId, messageIds: [messageId] });
|
||||||
|
forwardToSavedMessages({ scheduledAt });
|
||||||
|
showNotification({
|
||||||
|
message: {
|
||||||
|
key: 'ReminderSetToast',
|
||||||
|
options: {
|
||||||
|
withNodes: true,
|
||||||
|
withMarkdown: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (asPreview) {
|
||||||
|
return formattedDate ?? children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
ref={ref}
|
||||||
|
onClick={handleContextMenu}
|
||||||
|
onContextMenu={handleContextMenu}
|
||||||
|
className="text-entity-link"
|
||||||
|
dir="auto"
|
||||||
|
data-entity-type={ApiMessageEntityTypes.FormattedDate}
|
||||||
|
data-unix={entity.date}
|
||||||
|
data-format={formatToString(entity)}
|
||||||
|
title={canonicalDate}
|
||||||
|
>
|
||||||
|
{formattedDate ?? children}
|
||||||
|
<Menu
|
||||||
|
ref={menuRef}
|
||||||
|
isOpen={isContextMenuOpen}
|
||||||
|
anchor={contextMenuAnchor}
|
||||||
|
getTriggerElement={getTriggerElement}
|
||||||
|
getRootElement={getRootElement}
|
||||||
|
getMenuElement={getMenuElement}
|
||||||
|
getLayout={getLayout}
|
||||||
|
onClose={handleContextMenuClose}
|
||||||
|
onCloseAnimationEnd={handleContextMenuHide}
|
||||||
|
withPortal
|
||||||
|
autoClose
|
||||||
|
>
|
||||||
|
<MenuItem icon="copy" onClick={handleCopy}>{lang('MenuCopyDate')}</MenuItem>
|
||||||
|
{canSetReminder && (
|
||||||
|
<MenuItem icon="unmute" onClick={handleSetReminder}>{lang('SetReminder')}</MenuItem>
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
{calendar}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FormattedDate;
|
||||||
|
|
||||||
|
function getUpdateInterval(diffInSeconds: number) {
|
||||||
|
if (diffInSeconds < 60) {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diffInSeconds < 60 * 60) {
|
||||||
|
return 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatToString(entity: ApiMessageEntityFormattedDate) {
|
||||||
|
const { relative, shortTime, longTime, shortDate, longDate, dayOfWeek } = entity;
|
||||||
|
return [
|
||||||
|
relative && 'r',
|
||||||
|
dayOfWeek && 'w',
|
||||||
|
shortDate && 'd',
|
||||||
|
longDate && 'D',
|
||||||
|
shortTime && 't',
|
||||||
|
longTime && 'T',
|
||||||
|
].filter(Boolean).join('');
|
||||||
|
}
|
||||||
@ -16,6 +16,7 @@ import MentionLink from '../../middle/message/MentionLink';
|
|||||||
import Blockquote from '../Blockquote';
|
import Blockquote from '../Blockquote';
|
||||||
import CodeBlock from '../code/CodeBlock';
|
import CodeBlock from '../code/CodeBlock';
|
||||||
import CustomEmoji from '../CustomEmoji';
|
import CustomEmoji from '../CustomEmoji';
|
||||||
|
import FormattedDate from '../FormattedDate';
|
||||||
import SafeLink from '../SafeLink';
|
import SafeLink from '../SafeLink';
|
||||||
import Spoiler from '../spoiler/Spoiler';
|
import Spoiler from '../spoiler/Spoiler';
|
||||||
|
|
||||||
@ -511,6 +512,11 @@ function processEntity({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity.type === ApiMessageEntityTypes.FormattedDate && entity.date) { // Old entities can have missing fields
|
||||||
|
return <FormattedDate entity={entity} asPreview>{text}</FormattedDate>;
|
||||||
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,6 +674,16 @@ function processEntity({
|
|||||||
return (
|
return (
|
||||||
<span className="matching-text-highlight is-quote">{renderNestedMessagePart()}</span>
|
<span className="matching-text-highlight is-quote">{renderNestedMessagePart()}</span>
|
||||||
);
|
);
|
||||||
|
case ApiMessageEntityTypes.FormattedDate:
|
||||||
|
return (
|
||||||
|
<FormattedDate
|
||||||
|
entity={entity}
|
||||||
|
chatId={chatId}
|
||||||
|
messageId={messageId}
|
||||||
|
>
|
||||||
|
{renderNestedMessagePart()}
|
||||||
|
</FormattedDate>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return renderNestedMessagePart();
|
return renderNestedMessagePart();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,7 +89,7 @@ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
|
|||||||
: 'Conversation.ForwardTooltip.SavedMessages.One',
|
: 'Conversation.ForwardTooltip.SavedMessages.One',
|
||||||
);
|
);
|
||||||
|
|
||||||
forwardToSavedMessages();
|
forwardToSavedMessages({});
|
||||||
showNotification({ message });
|
showNotification({ message });
|
||||||
} else {
|
} else {
|
||||||
const chatId = recipientId;
|
const chatId = recipientId;
|
||||||
|
|||||||
@ -369,7 +369,7 @@ const Main = ({
|
|||||||
|
|
||||||
loadCountryList({ langCode: lang.code });
|
loadCountryList({ langCode: lang.code });
|
||||||
}
|
}
|
||||||
}, [lang, isMasterTab]);
|
}, [lang.code, isMasterTab]);
|
||||||
|
|
||||||
// Re-fetch cached saved emoji for `localDb`
|
// Re-fetch cached saved emoji for `localDb`
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -121,6 +121,7 @@ const ListItem = ({
|
|||||||
if (ref) {
|
if (ref) {
|
||||||
containerRef = ref;
|
containerRef = ref;
|
||||||
}
|
}
|
||||||
|
const menuRef = useRef<HTMLDivElement>();
|
||||||
const [isTouched, markIsTouched, unmarkIsTouched] = useFlag();
|
const [isTouched, markIsTouched, unmarkIsTouched] = useFlag();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -131,10 +132,7 @@ const ListItem = ({
|
|||||||
|
|
||||||
const getTriggerElement = useLastCallback(() => containerRef.current);
|
const getTriggerElement = useLastCallback(() => containerRef.current);
|
||||||
const getRootElement = useLastCallback(() => containerRef.current!.closest('.custom-scroll'));
|
const getRootElement = useLastCallback(() => containerRef.current!.closest('.custom-scroll'));
|
||||||
const getMenuElement = useLastCallback(() => {
|
const getMenuElement = useLastCallback(() => menuRef.current);
|
||||||
return (withPortalForMenu ? document.querySelector('#portals') : containerRef.current)!
|
|
||||||
.querySelector('.ListItem-context-menu .bubble');
|
|
||||||
});
|
|
||||||
const getLayout = useLastCallback(() => ({ withPortal: withPortalForMenu }));
|
const getLayout = useLastCallback(() => ({ withPortal: withPortalForMenu }));
|
||||||
|
|
||||||
const handleClickEvent = useLastCallback((e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
const handleClickEvent = useLastCallback((e: React.MouseEvent<HTMLElement, MouseEvent>) => {
|
||||||
@ -271,6 +269,7 @@ const ListItem = ({
|
|||||||
</ButtonElementTag>
|
</ButtonElementTag>
|
||||||
{contextActions && contextMenuAnchor !== undefined && (
|
{contextActions && contextMenuAnchor !== undefined && (
|
||||||
<Menu
|
<Menu
|
||||||
|
ref={menuRef}
|
||||||
isOpen={isContextMenuOpen}
|
isOpen={isContextMenuOpen}
|
||||||
anchor={contextMenuAnchor}
|
anchor={contextMenuAnchor}
|
||||||
getTriggerElement={getTriggerElement}
|
getTriggerElement={getTriggerElement}
|
||||||
|
|||||||
@ -2583,7 +2583,7 @@ addActionHandler('setForwardChatOrTopic', async (global, actions, payload): Prom
|
|||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('forwardToSavedMessages', (global, actions, payload): ActionReturnType => {
|
addActionHandler('forwardToSavedMessages', (global, actions, payload): ActionReturnType => {
|
||||||
const { tabId = getCurrentTabId() } = payload || {};
|
const { scheduledAt, tabId = getCurrentTabId() } = payload || {};
|
||||||
global = updateTabState(global, {
|
global = updateTabState(global, {
|
||||||
forwardMessages: {
|
forwardMessages: {
|
||||||
...selectTabState(global, tabId).forwardMessages,
|
...selectTabState(global, tabId).forwardMessages,
|
||||||
@ -2593,7 +2593,7 @@ addActionHandler('forwardToSavedMessages', (global, actions, payload): ActionRet
|
|||||||
setGlobal(global);
|
setGlobal(global);
|
||||||
|
|
||||||
actions.exitMessageSelectMode({ tabId });
|
actions.exitMessageSelectMode({ tabId });
|
||||||
actions.forwardMessages({ isSilent: true, tabId });
|
actions.forwardMessages({ isSilent: true, scheduledAt, tabId });
|
||||||
});
|
});
|
||||||
|
|
||||||
addActionHandler('forwardStory', (global, actions, payload): ActionReturnType => {
|
addActionHandler('forwardStory', (global, actions, payload): ActionReturnType => {
|
||||||
|
|||||||
@ -2023,7 +2023,9 @@ export interface ActionPayloads {
|
|||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
exitForwardMode: WithTabId | undefined;
|
exitForwardMode: WithTabId | undefined;
|
||||||
changeRecipient: WithTabId | undefined;
|
changeRecipient: WithTabId | undefined;
|
||||||
forwardToSavedMessages: WithTabId | undefined;
|
forwardToSavedMessages: {
|
||||||
|
scheduledAt?: number;
|
||||||
|
} & WithTabId;
|
||||||
forwardStory: {
|
forwardStory: {
|
||||||
toChatId: string;
|
toChatId: string;
|
||||||
} & WithTabId;
|
} & WithTabId;
|
||||||
|
|||||||
@ -210,7 +210,7 @@ function createClasses(classesType: 'constructor' | 'request', params: Generatio
|
|||||||
const flagGroupSuffix = arg.flagGroup > 1 ? arg.flagGroup : '';
|
const flagGroupSuffix = arg.flagGroup > 1 ? arg.flagGroup : '';
|
||||||
const flagValue = args[`flags${flagGroupSuffix}`] & (1 << arg.flagIndex);
|
const flagValue = args[`flags${flagGroupSuffix}`] & (1 << arg.flagIndex);
|
||||||
if (arg.type === 'true') {
|
if (arg.type === 'true') {
|
||||||
args[argName] = Boolean(flagValue);
|
args[argName] = flagValue ? true : undefined;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -777,7 +777,6 @@ export type SendMessageParams = {
|
|||||||
messagePriceInStars?: number;
|
messagePriceInStars?: number;
|
||||||
localMessage?: ApiMessage;
|
localMessage?: ApiMessage;
|
||||||
forwardedLocalMessagesSlice?: ForwardedLocalMessagesSlice;
|
forwardedLocalMessagesSlice?: ForwardedLocalMessagesSlice;
|
||||||
isForwarding?: boolean;
|
|
||||||
forwardParams?: ForwardMessagesParams;
|
forwardParams?: ForwardMessagesParams;
|
||||||
isStoryReply?: boolean;
|
isStoryReply?: boolean;
|
||||||
suggestedMedia?: MediaContent;
|
suggestedMedia?: MediaContent;
|
||||||
|
|||||||
3
src/types/language.d.ts
vendored
3
src/types/language.d.ts
vendored
@ -2036,6 +2036,9 @@ export interface LangPair {
|
|||||||
'RankEditSave': undefined;
|
'RankEditSave': undefined;
|
||||||
'RankEditTextOwn': undefined;
|
'RankEditTextOwn': undefined;
|
||||||
'MenuAddCaption': undefined;
|
'MenuAddCaption': undefined;
|
||||||
|
'MenuCopyDate': undefined;
|
||||||
|
'DateCopiedToast': undefined;
|
||||||
|
'ReminderSetToast': undefined;
|
||||||
'NoForwardsRequestReject': undefined;
|
'NoForwardsRequestReject': undefined;
|
||||||
'NoForwardsRequestAccept': undefined;
|
'NoForwardsRequestAccept': undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -239,6 +239,10 @@ function getHourCycle(timeFormat: TimeFormat) {
|
|||||||
return timeFormat === '12h' ? 'h12' : 'h23';
|
return timeFormat === '12h' ? 'h12' : 'h23';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function secondsToDate(seconds: number) {
|
||||||
|
return new Date(seconds * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
function serializeRecord(record: object) {
|
function serializeRecord(record: object) {
|
||||||
return Object.entries(record as Record<string, unknown>)
|
return Object.entries(record as Record<string, unknown>)
|
||||||
.filter(([, value]) => value !== undefined)
|
.filter(([, value]) => value !== undefined)
|
||||||
|
|||||||
@ -356,7 +356,7 @@ export function setTimeFormat(timeFormat: TimeFormat) {
|
|||||||
|
|
||||||
currentTimeFormat = timeFormat;
|
currentTimeFormat = timeFormat;
|
||||||
resetDateFormatCache();
|
resetDateFormatCache();
|
||||||
translationFn.timeFormat = currentTimeFormat;
|
translationFn = createTranslationFn();
|
||||||
scheduleCallbacks();
|
scheduleCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -198,13 +198,21 @@ function getEntityDataFromNode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === ApiMessageEntityTypes.CustomEmoji) {
|
if (type === ApiMessageEntityTypes.CustomEmoji) {
|
||||||
|
const nodeElement = node as HTMLElement;
|
||||||
|
const documentId = nodeElement.dataset.documentId || nodeElement.getAttribute('emoji-id');
|
||||||
|
if (!documentId) {
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
entity: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
entity: {
|
entity: {
|
||||||
type,
|
type,
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
documentId: (node as HTMLImageElement).dataset.documentId!,
|
documentId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -229,6 +237,28 @@ function getEntityDataFromNode(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === ApiMessageEntityTypes.FormattedDate) {
|
||||||
|
const date = Number((node as HTMLElement).dataset.unix);
|
||||||
|
if (Number.isNaN(date)) {
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
entity: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const format = (node as HTMLElement).dataset.format;
|
||||||
|
const relative = format?.includes('r') || undefined;
|
||||||
|
const dayOfWeek = format?.includes('w') || undefined;
|
||||||
|
const shortDate = format?.includes('d') || undefined;
|
||||||
|
const longDate = format?.includes('D') || undefined;
|
||||||
|
const shortTime = format?.includes('t') || undefined;
|
||||||
|
const longTime = format?.includes('T') || undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
index,
|
||||||
|
entity: { type, offset, length, date, relative, dayOfWeek, shortDate, longDate, shortTime, longTime },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
index,
|
index,
|
||||||
entity: {
|
entity: {
|
||||||
@ -279,5 +309,13 @@ function getEntityTypeFromNode(node: ChildNode): ApiMessageEntityTypes | undefin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.nodeName === 'TG-TIME') {
|
||||||
|
return ApiMessageEntityTypes.FormattedDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.nodeName === 'TG-EMOJI') {
|
||||||
|
return ApiMessageEntityTypes.CustomEmoji;
|
||||||
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user