Translation: Add Cocoon info (#6646)
This commit is contained in:
parent
6605a90606
commit
baff436709
6
src/@types/global.d.ts
vendored
6
src/@types/global.d.ts
vendored
@ -84,6 +84,12 @@ declare module '*.jpg' {
|
|||||||
const url: string;
|
const url: string;
|
||||||
export default url;
|
export default url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.webp' {
|
||||||
|
const url: string;
|
||||||
|
export default url;
|
||||||
|
}
|
||||||
|
|
||||||
declare module '*.svg' {
|
declare module '*.svg' {
|
||||||
const url: string;
|
const url: string;
|
||||||
export default url;
|
export default url;
|
||||||
|
|||||||
BIN
src/assets/cocoon.webp
Normal file
BIN
src/assets/cocoon.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@ -2608,6 +2608,23 @@
|
|||||||
"SettingsDataClearMediaCache" = "Clear Media Cache";
|
"SettingsDataClearMediaCache" = "Clear Media Cache";
|
||||||
"SettingsDataClearMediaCacheDescription" = "Deletes locally cached media for this account";
|
"SettingsDataClearMediaCacheDescription" = "Deletes locally cached media for this account";
|
||||||
"SettingsDataClearMediaDone" = "Media cache cleared";
|
"SettingsDataClearMediaDone" = "Media cache cleared";
|
||||||
|
"TranslateMenuCocoon" = "Translations are powered by 🥚 **Cocoon**. {link}";
|
||||||
|
"TranslateMenuCocoonLinkText" = "How does it work?";
|
||||||
|
"CocoonTitle" = "Cocoon";
|
||||||
|
"CocoonDescription" = "Cocoon (**Co**nfidential **Co**mpute **O**pen **N**etwork)\nhandles AI tasks safely and efficiently.";
|
||||||
|
"CocoonFeature1Title" = "Private";
|
||||||
|
"CocoonFeature1Text" = "No third party can access any data, such as translations, inside **{username}**.";
|
||||||
|
"CocoonFeature1Username" = "@cocoon";
|
||||||
|
"CocoonFeature1UsernameLink" = "https://t.me/cocoon";
|
||||||
|
"CocoonFeature2Title" = "Efficient";
|
||||||
|
"CocoonFeature2Text" = "Cocoon has allowed Telegram to reduce translation cost by 6x.";
|
||||||
|
"CocoonFeature3Title" = "For Everyone";
|
||||||
|
"CocoonFeature3Text" = "Any developer can use Cocoon for AI features. Learn more at **{link}**.";
|
||||||
|
"CocoonFeature3LinkText" = "cocoon.org";
|
||||||
|
"CocoonFeature3Link" = "https://cocoon.org";
|
||||||
|
"CocoonFooterText" = "Want to integrate Cocoon into your projects?\nReach out **{link}**";
|
||||||
|
"CocoonFooterLinkText" = "directly to @cocoon";
|
||||||
|
"CocoonFooterLink" = "https://t.me/cocoon?direct";
|
||||||
"ChatListAuctionTitle_one" = "Active Auction";
|
"ChatListAuctionTitle_one" = "Active Auction";
|
||||||
"ChatListAuctionTitle_other" = "{count} Active Auctions";
|
"ChatListAuctionTitle_other" = "{count} Active Auctions";
|
||||||
"ChatListAuctionWinning" = "You are winning";
|
"ChatListAuctionWinning" = "You are winning";
|
||||||
|
|||||||
@ -108,3 +108,4 @@ export { default as ProfileRatingModal } from '../components/modals/profileRatin
|
|||||||
export { default as QuickPreviewModal } from '../components/modals/quickPreview/QuickPreviewModal';
|
export { default as QuickPreviewModal } from '../components/modals/quickPreview/QuickPreviewModal';
|
||||||
export { default as StealthModeModal } from '../components/modals/storyStealthMode/StealthModeModal';
|
export { default as StealthModeModal } from '../components/modals/storyStealthMode/StealthModeModal';
|
||||||
export { default as QuickChatPickerModal } from '../components/modals/quickChatPicker/QuickChatPickerModal';
|
export { default as QuickChatPickerModal } from '../components/modals/quickChatPicker/QuickChatPickerModal';
|
||||||
|
export { default as CocoonModal } from '../components/modals/cocoon/CocoonModal';
|
||||||
|
|||||||
@ -17,6 +17,8 @@ const DEFAULT_PARTICLE_PARAMS = {
|
|||||||
centerShift: [0, -36] as const,
|
centerShift: [0, -36] as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MIN_BURST_INTERVAL = 8;
|
||||||
|
|
||||||
const InteractiveSparkles = ({
|
const InteractiveSparkles = ({
|
||||||
color = 'purple',
|
color = 'purple',
|
||||||
centerShift = DEFAULT_PARTICLE_PARAMS.centerShift,
|
centerShift = DEFAULT_PARTICLE_PARAMS.centerShift,
|
||||||
@ -25,6 +27,7 @@ const InteractiveSparkles = ({
|
|||||||
onRequestAnimation,
|
onRequestAnimation,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>();
|
const canvasRef = useRef<HTMLCanvasElement>();
|
||||||
|
const lastBurstTimeRef = useRef<number>(0);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
if (isDisabled) return undefined;
|
if (isDisabled) return undefined;
|
||||||
@ -41,6 +44,11 @@ const InteractiveSparkles = ({
|
|||||||
const animate = () => {
|
const animate = () => {
|
||||||
if (isDisabled) return;
|
if (isDisabled) return;
|
||||||
|
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - lastBurstTimeRef.current < MIN_BURST_INTERVAL) return;
|
||||||
|
|
||||||
|
lastBurstTimeRef.current = now;
|
||||||
|
|
||||||
setupParticles(canvasRef.current!, {
|
setupParticles(canvasRef.current!, {
|
||||||
color: PARTICLE_COLORS[`${color}Gradient`],
|
color: PARTICLE_COLORS[`${color}Gradient`],
|
||||||
centerShift,
|
centerShift,
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import type { IAnchorPosition, MessageListType, ThreadId } from '../../types';
|
|||||||
import { MAIN_THREAD_ID } from '../../api/types';
|
import { MAIN_THREAD_ID } from '../../api/types';
|
||||||
import { ManagementScreens } from '../../types';
|
import { ManagementScreens } from '../../types';
|
||||||
|
|
||||||
|
import { COCOON_EMOJI_ID } from '../../config';
|
||||||
import { requestMeasure, requestNextMutation } from '../../lib/fasterdom/fasterdom';
|
import { requestMeasure, requestNextMutation } from '../../lib/fasterdom/fasterdom';
|
||||||
import {
|
import {
|
||||||
getHasAdminRight,
|
getHasAdminRight,
|
||||||
@ -38,11 +39,14 @@ import { isUserId } from '../../util/entities/ids';
|
|||||||
import focusNoScroll from '../../util/focusNoScroll';
|
import focusNoScroll from '../../util/focusNoScroll';
|
||||||
|
|
||||||
import { useHotkeys } from '../../hooks/useHotkeys';
|
import { useHotkeys } from '../../hooks/useHotkeys';
|
||||||
|
import useLang from '../../hooks/useLang';
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
import useOldLang from '../../hooks/useOldLang';
|
import useOldLang from '../../hooks/useOldLang';
|
||||||
|
|
||||||
|
import CustomEmoji from '../common/CustomEmoji';
|
||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import DropdownMenu from '../ui/DropdownMenu';
|
import DropdownMenu from '../ui/DropdownMenu';
|
||||||
|
import Link from '../ui/Link';
|
||||||
import MenuItem from '../ui/MenuItem';
|
import MenuItem from '../ui/MenuItem';
|
||||||
import MenuSeparator from '../ui/MenuSeparator';
|
import MenuSeparator from '../ui/MenuSeparator';
|
||||||
import HeaderMenuContainer from './HeaderMenuContainer.async';
|
import HeaderMenuContainer from './HeaderMenuContainer.async';
|
||||||
@ -142,9 +146,12 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
unblockUser,
|
unblockUser,
|
||||||
setViewForumAsMessages,
|
setViewForumAsMessages,
|
||||||
openFrozenAccountModal,
|
openFrozenAccountModal,
|
||||||
|
openCocoonModal,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
const menuButtonRef = useRef<HTMLButtonElement>();
|
const menuButtonRef = useRef<HTMLButtonElement>();
|
||||||
const lang = useOldLang();
|
const oldLang = useOldLang();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
const [menuAnchor, setMenuAnchor] = useState<IAnchorPosition | undefined>(undefined);
|
const [menuAnchor, setMenuAnchor] = useState<IAnchorPosition | undefined>(undefined);
|
||||||
|
|
||||||
@ -166,7 +173,8 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
joinChannel({ chatId });
|
joinChannel({ chatId });
|
||||||
if (shouldSendJoinRequest) {
|
if (shouldSendJoinRequest) {
|
||||||
showNotification({
|
showNotification({
|
||||||
message: isChannel ? lang('RequestToJoinChannelSentDescription') : lang('RequestToJoinGroupSentDescription'),
|
message: isChannel ? oldLang('RequestToJoinChannelSentDescription')
|
||||||
|
: oldLang('RequestToJoinGroupSentDescription'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -239,21 +247,21 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
const getTextWithLanguage = useCallback((langKey: string, langCode: string) => {
|
const getTextWithLanguage = useCallback((langKey: string, langCode: string) => {
|
||||||
const simplified = langCode.split('-')[0];
|
const simplified = langCode.split('-')[0];
|
||||||
const translationKey = `TranslateLanguage${simplified.toUpperCase()}`;
|
const translationKey = `TranslateLanguage${simplified.toUpperCase()}`;
|
||||||
const name = lang(translationKey);
|
const name = oldLang(translationKey);
|
||||||
if (name !== translationKey) {
|
if (name !== translationKey) {
|
||||||
return lang(langKey, name);
|
return oldLang(langKey, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const translatedNames = new Intl.DisplayNames([language], { type: 'language' });
|
const translatedNames = new Intl.DisplayNames([language], { type: 'language' });
|
||||||
const translatedName = translatedNames.of(langCode)!;
|
const translatedName = translatedNames.of(langCode)!;
|
||||||
return lang(`${langKey}Other`, translatedName);
|
return oldLang(`${langKey}Other`, translatedName);
|
||||||
}, [language, lang]);
|
}, [language, oldLang]);
|
||||||
|
|
||||||
const buttonText = useMemo(() => {
|
const buttonText = useMemo(() => {
|
||||||
if (isTranslating) return lang('ShowOriginalButton');
|
if (isTranslating) return oldLang('ShowOriginalButton');
|
||||||
|
|
||||||
return getTextWithLanguage('TranslateToButton', translationLanguage);
|
return getTextWithLanguage('TranslateToButton', translationLanguage);
|
||||||
}, [translationLanguage, getTextWithLanguage, isTranslating, lang]);
|
}, [translationLanguage, getTextWithLanguage, isTranslating, oldLang]);
|
||||||
|
|
||||||
const doNotTranslateText = useMemo(() => {
|
const doNotTranslateText = useMemo(() => {
|
||||||
if (!detectedChatLanguage) return undefined;
|
if (!detectedChatLanguage) return undefined;
|
||||||
@ -270,6 +278,10 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
openChatLanguageModal({ chatId });
|
openChatLanguageModal({ chatId });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleCocoonClick = useLastCallback(() => {
|
||||||
|
openCocoonModal();
|
||||||
|
});
|
||||||
|
|
||||||
const handleDoNotTranslate = useLastCallback(() => {
|
const handleDoNotTranslate = useLastCallback(() => {
|
||||||
if (!detectedChatLanguage) return;
|
if (!detectedChatLanguage) return;
|
||||||
|
|
||||||
@ -294,11 +306,11 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
size="smaller"
|
size="smaller"
|
||||||
className={isOpen ? 'active' : ''}
|
className={isOpen ? 'active' : ''}
|
||||||
onClick={onTrigger}
|
onClick={onTrigger}
|
||||||
ariaLabel={lang('TranslateMessage')}
|
ariaLabel={oldLang('TranslateMessage')}
|
||||||
iconName="language"
|
iconName="language"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, [isRightColumnShown, lang]);
|
}, [isRightColumnShown, oldLang]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="HeaderActions">
|
<div className="HeaderActions">
|
||||||
@ -312,12 +324,28 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
{buttonText}
|
{buttonText}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem icon="replace" onClick={handleChangeLanguage}>
|
<MenuItem icon="replace" onClick={handleChangeLanguage}>
|
||||||
{lang('Chat.Translate.Menu.To')}
|
{oldLang('Chat.Translate.Menu.To')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuSeparator />
|
<MenuSeparator />
|
||||||
{detectedChatLanguage
|
{detectedChatLanguage
|
||||||
&& <MenuItem icon="hand-stop" onClick={handleDoNotTranslate}>{doNotTranslateText}</MenuItem>}
|
&& <MenuItem icon="hand-stop" onClick={handleDoNotTranslate}>{doNotTranslateText}</MenuItem>}
|
||||||
<MenuItem icon="close-circle" onClick={handleHide}>{lang('Hide')}</MenuItem>
|
<MenuItem icon="close-circle" onClick={handleHide}>{oldLang('Hide')}</MenuItem>
|
||||||
|
<MenuSeparator />
|
||||||
|
<MenuItem withWrap onClick={handleCocoonClick}>
|
||||||
|
{lang('TranslateMenuCocoon', {
|
||||||
|
link: (
|
||||||
|
<Link isPrimary onClick={(e) => e.preventDefault()}>
|
||||||
|
{lang('TranslateMenuCocoonLinkText')}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
}, {
|
||||||
|
withNodes: true,
|
||||||
|
withMarkdown: true,
|
||||||
|
specialReplacement: {
|
||||||
|
'🥚': <CustomEmoji documentId={COCOON_EMOJI_ID} />,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
</MenuItem>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
@ -329,7 +357,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
fluid
|
fluid
|
||||||
onClick={handleSubscribeClick}
|
onClick={handleSubscribeClick}
|
||||||
>
|
>
|
||||||
{lang(isChannel ? 'ProfileJoinChannel' : 'ProfileJoinGroup')}
|
{oldLang(isChannel ? 'ProfileJoinChannel' : 'ProfileJoinGroup')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{canExpandActions && shouldSendJoinRequest && (
|
{canExpandActions && shouldSendJoinRequest && (
|
||||||
@ -339,7 +367,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
fluid
|
fluid
|
||||||
onClick={handleSubscribeClick}
|
onClick={handleSubscribeClick}
|
||||||
>
|
>
|
||||||
{lang('ChannelJoinRequest')}
|
{oldLang('ChannelJoinRequest')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{canExpandActions && canStartBot && (
|
{canExpandActions && canStartBot && (
|
||||||
@ -349,7 +377,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
fluid
|
fluid
|
||||||
onClick={handleStartBot}
|
onClick={handleStartBot}
|
||||||
>
|
>
|
||||||
{lang('BotStart')}
|
{oldLang('BotStart')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{canExpandActions && canRestartBot && (
|
{canExpandActions && canRestartBot && (
|
||||||
@ -359,7 +387,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
fluid
|
fluid
|
||||||
onClick={handleRestartBot}
|
onClick={handleRestartBot}
|
||||||
>
|
>
|
||||||
{lang('BotRestart')}
|
{oldLang('BotRestart')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{canExpandActions && canUnblock && (
|
{canExpandActions && canUnblock && (
|
||||||
@ -369,7 +397,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
fluid
|
fluid
|
||||||
onClick={handleUnblock}
|
onClick={handleUnblock}
|
||||||
>
|
>
|
||||||
{lang('Unblock')}
|
{oldLang('Unblock')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{canSearch && (
|
{canSearch && (
|
||||||
@ -379,7 +407,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
color="translucent"
|
color="translucent"
|
||||||
size="smaller"
|
size="smaller"
|
||||||
onClick={handleSearchClick}
|
onClick={handleSearchClick}
|
||||||
ariaLabel={lang('Conversation.SearchPlaceholder')}
|
ariaLabel={oldLang('Conversation.SearchPlaceholder')}
|
||||||
iconName="search"
|
iconName="search"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -404,7 +432,7 @@ const HeaderActions: FC<OwnProps & StateProps> = ({
|
|||||||
size="smaller"
|
size="smaller"
|
||||||
iconName="user"
|
iconName="user"
|
||||||
onClick={handleJoinRequestsClick}
|
onClick={handleJoinRequestsClick}
|
||||||
ariaLabel={isChannel ? lang('SubscribeRequests') : lang('MemberRequests')}
|
ariaLabel={isChannel ? oldLang('SubscribeRequests') : oldLang('MemberRequests')}
|
||||||
>
|
>
|
||||||
<div className="badge">{pendingJoinRequests}</div>
|
<div className="badge">{pendingJoinRequests}</div>
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -583,13 +583,13 @@
|
|||||||
|
|
||||||
&:not(.custom-shape) .text-content {
|
&:not(.custom-shape) .text-content {
|
||||||
.emoji {
|
.emoji {
|
||||||
width: calc(1.25 * var(--message-text-size, 1rem));
|
width: 1.25em;
|
||||||
height: calc(1.25 * var(--message-text-size, 1rem));
|
height: 1.25em;
|
||||||
background-size: calc(1.25 * var(--message-text-size, 1rem));
|
background-size: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-emoji {
|
.custom-emoji {
|
||||||
--custom-emoji-size: max(calc(1.25 * var(--message-text-size, 1rem)), 20px);
|
--custom-emoji-size: max(1.25em, 20px);
|
||||||
|
|
||||||
width: var(--custom-emoji-size);
|
width: var(--custom-emoji-size);
|
||||||
height: var(--custom-emoji-size);
|
height: var(--custom-emoji-size);
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import BirthdaySetupModal from './birthday/BirthdaySetupModal.async';
|
|||||||
import BoostModal from './boost/BoostModal.async';
|
import BoostModal from './boost/BoostModal.async';
|
||||||
import ChatInviteModal from './chatInvite/ChatInviteModal.async';
|
import ChatInviteModal from './chatInvite/ChatInviteModal.async';
|
||||||
import ChatlistModal from './chatlist/ChatlistModal.async';
|
import ChatlistModal from './chatlist/ChatlistModal.async';
|
||||||
|
import CocoonModal from './cocoon/CocoonModal.async';
|
||||||
import CollectibleInfoModal from './collectible/CollectibleInfoModal.async';
|
import CollectibleInfoModal from './collectible/CollectibleInfoModal.async';
|
||||||
import DeleteAccountModal from './deleteAccount/DeleteAccountModal.async';
|
import DeleteAccountModal from './deleteAccount/DeleteAccountModal.async';
|
||||||
import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.async';
|
import EmojiStatusAccessModal from './emojiStatusAccess/EmojiStatusAccessModal.async';
|
||||||
@ -130,7 +131,8 @@ type ModalKey = keyof Pick<TabState,
|
|||||||
'storyStealthModal' |
|
'storyStealthModal' |
|
||||||
'isPasskeyModalOpen' |
|
'isPasskeyModalOpen' |
|
||||||
'birthdaySetupModal' |
|
'birthdaySetupModal' |
|
||||||
'isQuickChatPickerOpen'
|
'isQuickChatPickerOpen' |
|
||||||
|
'isCocoonModalOpen'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
@ -207,6 +209,7 @@ const MODALS: ModalRegistry = {
|
|||||||
isPasskeyModalOpen: PasskeyModal,
|
isPasskeyModalOpen: PasskeyModal,
|
||||||
birthdaySetupModal: BirthdaySetupModal,
|
birthdaySetupModal: BirthdaySetupModal,
|
||||||
isQuickChatPickerOpen: QuickChatPickerModal,
|
isQuickChatPickerOpen: QuickChatPickerModal,
|
||||||
|
isCocoonModalOpen: CocoonModal,
|
||||||
};
|
};
|
||||||
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
const MODAL_KEYS = Object.keys(MODALS) as ModalKey[];
|
||||||
const MODAL_ENTRIES = Object.entries(MODALS) as Entries<ModalRegistry>;
|
const MODAL_ENTRIES = Object.entries(MODALS) as Entries<ModalRegistry>;
|
||||||
|
|||||||
14
src/components/modals/cocoon/CocoonModal.async.tsx
Normal file
14
src/components/modals/cocoon/CocoonModal.async.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import type { OwnProps } from './CocoonModal';
|
||||||
|
|
||||||
|
import { Bundles } from '../../../util/moduleLoader';
|
||||||
|
|
||||||
|
import useModuleLoader from '../../../hooks/useModuleLoader';
|
||||||
|
|
||||||
|
const CocoonModalAsync = (props: OwnProps) => {
|
||||||
|
const { modal } = props;
|
||||||
|
const CocoonModal = useModuleLoader(Bundles.Extra, 'CocoonModal', !modal);
|
||||||
|
|
||||||
|
return CocoonModal ? <CocoonModal {...props} /> : undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CocoonModalAsync;
|
||||||
26
src/components/modals/cocoon/CocoonModal.module.scss
Normal file
26
src/components/modals/cocoon/CocoonModal.module.scss
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
.header {
|
||||||
|
position: relative;
|
||||||
|
margin-top: -1rem;
|
||||||
|
margin-inline: -1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footerText {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-align: center;
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
.egg {
|
||||||
|
transition: transform 0.25s ease-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
108
src/components/modals/cocoon/CocoonModal.tsx
Normal file
108
src/components/modals/cocoon/CocoonModal.tsx
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import { memo, useMemo } from '@teact';
|
||||||
|
import { getActions } from '../../../global';
|
||||||
|
|
||||||
|
import type { TabState } from '../../../global/types';
|
||||||
|
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
|
import SafeLink from '../../common/SafeLink';
|
||||||
|
import Button from '../../ui/Button';
|
||||||
|
import Link from '../../ui/Link';
|
||||||
|
import ParticlesHeader from '../common/ParticlesHeader';
|
||||||
|
import TableAboutModal, { type TableAboutData } from '../common/TableAboutModal';
|
||||||
|
|
||||||
|
import styles from './CocoonModal.module.scss';
|
||||||
|
|
||||||
|
export type OwnProps = {
|
||||||
|
modal: TabState['isCocoonModalOpen'];
|
||||||
|
};
|
||||||
|
|
||||||
|
const CocoonModal = ({ modal }: OwnProps) => {
|
||||||
|
const { closeCocoonModal, openTelegramLink } = getActions();
|
||||||
|
const isOpen = Boolean(modal);
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
|
const handleClose = useLastCallback(() => {
|
||||||
|
closeCocoonModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
const openLinkAndClose = useLastCallback((url: string) => {
|
||||||
|
openTelegramLink({ url });
|
||||||
|
handleClose();
|
||||||
|
});
|
||||||
|
|
||||||
|
const listItemData = useMemo(() => {
|
||||||
|
const feature1Description = lang('CocoonFeature1Text', {
|
||||||
|
username: (
|
||||||
|
<Link
|
||||||
|
isPrimary
|
||||||
|
onClick={() => {
|
||||||
|
openLinkAndClose(lang('CocoonFeature1UsernameLink'));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{lang('CocoonFeature1Username')}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
}, { withNodes: true, withMarkdown: true });
|
||||||
|
|
||||||
|
const feature3Description = lang('CocoonFeature3Text', {
|
||||||
|
link: <SafeLink url={lang('CocoonFeature3Link')} text={lang('CocoonFeature3LinkText')} />,
|
||||||
|
}, {
|
||||||
|
withNodes: true,
|
||||||
|
withMarkdown: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return [
|
||||||
|
['lock', lang('CocoonFeature1Title'), feature1Description],
|
||||||
|
['stats', lang('CocoonFeature2Title'), lang('CocoonFeature2Text')],
|
||||||
|
['gift', lang('CocoonFeature3Title'), feature3Description],
|
||||||
|
] satisfies TableAboutData;
|
||||||
|
}, [lang]);
|
||||||
|
|
||||||
|
const header = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<ParticlesHeader
|
||||||
|
className={styles.header}
|
||||||
|
modelClassName={styles.egg}
|
||||||
|
model="ai-egg"
|
||||||
|
color="purple"
|
||||||
|
title={lang('CocoonTitle')}
|
||||||
|
description={lang('CocoonDescription', undefined, { withNodes: true, withMarkdown: true })}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}, [lang]);
|
||||||
|
|
||||||
|
const footer = useMemo(() => {
|
||||||
|
return (
|
||||||
|
<div className={styles.footer}>
|
||||||
|
<span className={styles.footerText}>
|
||||||
|
{lang('CocoonFooterText', {
|
||||||
|
link: (
|
||||||
|
<Link isPrimary onClick={() => openLinkAndClose(lang('CocoonFooterLink'))}>
|
||||||
|
{lang('CocoonFooterLinkText')}
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
}, { withNodes: true, withMarkdown: true })}
|
||||||
|
</span>
|
||||||
|
<Button iconName="understood" onClick={handleClose}>
|
||||||
|
{lang('ButtonUnderstood')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [lang]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableAboutModal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={closeCocoonModal}
|
||||||
|
listItemData={listItemData}
|
||||||
|
withSeparator
|
||||||
|
header={header}
|
||||||
|
footer={footer}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default memo(CocoonModal);
|
||||||
@ -5,6 +5,29 @@
|
|||||||
padding-top: 9rem;
|
padding-top: 9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ai-egg {
|
||||||
|
padding-top: 10rem;
|
||||||
|
background-color: #061029;
|
||||||
|
background-image: radial-gradient(circle at center, #FFFFFF08 0%, #00000000 50%);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: transparent;
|
||||||
|
|
||||||
|
background-image: linear-gradient(90deg, #67c9ff 0%, #cb56ff 100%);
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
color: #b8c9ef;
|
||||||
|
:global(b) {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.particles {
|
.particles {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -41,3 +64,10 @@
|
|||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cocoon {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top: 1.75rem;
|
||||||
|
height: 8.125rem;
|
||||||
|
}
|
||||||
|
|||||||
@ -15,14 +15,17 @@ import SwayingStar from './SwayingStar.tsx';
|
|||||||
|
|
||||||
import styles from './ParticlesHeader.module.scss';
|
import styles from './ParticlesHeader.module.scss';
|
||||||
|
|
||||||
|
import Cocoon from '../../../assets/cocoon.webp';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
model: 'swaying-star' | 'speeding-diamond' | 'sticker';
|
model: 'swaying-star' | 'speeding-diamond' | 'ai-egg' | 'sticker';
|
||||||
sticker?: ApiSticker;
|
sticker?: ApiSticker;
|
||||||
color: 'purple' | 'gold' | 'blue';
|
color: 'purple' | 'gold' | 'blue';
|
||||||
title: TeactNode;
|
title: TeactNode;
|
||||||
description: TeactNode;
|
description: TeactNode;
|
||||||
isDisabled?: boolean;
|
isDisabled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
modelClassName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GIFT_STICKER_SIZE = 8 * REM;
|
const GIFT_STICKER_SIZE = 8 * REM;
|
||||||
@ -39,6 +42,7 @@ function ParticlesHeader({
|
|||||||
description,
|
description,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
className,
|
className,
|
||||||
|
modelClassName,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const stickerRef = useRef<HTMLDivElement>();
|
const stickerRef = useRef<HTMLDivElement>();
|
||||||
const triggerSparklesRef = useRef<(() => void) | undefined>();
|
const triggerSparklesRef = useRef<(() => void) | undefined>();
|
||||||
@ -52,7 +56,7 @@ function ParticlesHeader({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={buildClassName(styles.root, className)}>
|
<div className={buildClassName(styles.root, styles[model], className)}>
|
||||||
<InteractiveSparkles
|
<InteractiveSparkles
|
||||||
color={color}
|
color={color}
|
||||||
centerShift={PARTICLE_PARAMS.centerShift}
|
centerShift={PARTICLE_PARAMS.centerShift}
|
||||||
@ -63,16 +67,27 @@ function ParticlesHeader({
|
|||||||
|
|
||||||
{model === 'swaying-star' ? (
|
{model === 'swaying-star' ? (
|
||||||
<SwayingStar
|
<SwayingStar
|
||||||
|
className={modelClassName}
|
||||||
color={color as 'purple' | 'gold'}
|
color={color as 'purple' | 'gold'}
|
||||||
centerShift={PARTICLE_PARAMS.centerShift}
|
centerShift={PARTICLE_PARAMS.centerShift}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
/>
|
/>
|
||||||
|
) : model === 'ai-egg' ? (
|
||||||
|
<img
|
||||||
|
src={Cocoon}
|
||||||
|
alt=""
|
||||||
|
role="presentation"
|
||||||
|
aria-hidden="true"
|
||||||
|
className={buildClassName(styles.cocoon, modelClassName)}
|
||||||
|
draggable={false}
|
||||||
|
onMouseMove={handleMouseMove}
|
||||||
|
/>
|
||||||
) : model === 'speeding-diamond' ? (
|
) : model === 'speeding-diamond' ? (
|
||||||
<SpeedingDiamond onMouseMove={handleMouseMove} />
|
<SpeedingDiamond className={modelClassName} onMouseMove={handleMouseMove} />
|
||||||
) : model === 'sticker' && sticker && (
|
) : model === 'sticker' && sticker && (
|
||||||
<div
|
<div
|
||||||
ref={stickerRef}
|
ref={stickerRef}
|
||||||
className={styles.stickerWrapper}
|
className={buildClassName(styles.stickerWrapper, modelClassName)}
|
||||||
style={`width: ${GIFT_STICKER_SIZE}px; height: ${GIFT_STICKER_SIZE}px`}
|
style={`width: ${GIFT_STICKER_SIZE}px; height: ${GIFT_STICKER_SIZE}px`}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { memo, useState } from '@teact';
|
|||||||
|
|
||||||
import { requestMutation } from '../../../lib/fasterdom/fasterdom.ts';
|
import { requestMutation } from '../../../lib/fasterdom/fasterdom.ts';
|
||||||
import { animateSingle } from '../../../util/animation.ts';
|
import { animateSingle } from '../../../util/animation.ts';
|
||||||
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets.ts';
|
import { LOCAL_TGS_URLS } from '../../common/helpers/animatedAssets.ts';
|
||||||
|
|
||||||
import useLastCallback from '../../../hooks/useLastCallback.ts';
|
import useLastCallback from '../../../hooks/useLastCallback.ts';
|
||||||
@ -13,6 +14,7 @@ import styles from './SpeedingDiamond.module.scss';
|
|||||||
import diamondPreviewUrl from '../../../assets/diamond.png';
|
import diamondPreviewUrl from '../../../assets/diamond.png';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
|
className?: string;
|
||||||
onMouseMove: NoneToVoidFunction;
|
onMouseMove: NoneToVoidFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +26,7 @@ const SLOWDOWN_DURATION = 1500;
|
|||||||
let slowdownTimeout: number | undefined;
|
let slowdownTimeout: number | undefined;
|
||||||
let isAnimating = true;
|
let isAnimating = true;
|
||||||
|
|
||||||
function SpeedingDiamond({ onMouseMove }: OwnProps) {
|
function SpeedingDiamond({ className, onMouseMove }: OwnProps) {
|
||||||
const [speed, setSpeed] = useState(MIN_SPEED);
|
const [speed, setSpeed] = useState(MIN_SPEED);
|
||||||
|
|
||||||
const handleMouseMove = useLastCallback(() => {
|
const handleMouseMove = useLastCallback(() => {
|
||||||
@ -58,7 +60,7 @@ function SpeedingDiamond({ onMouseMove }: OwnProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={buildClassName(styles.root, className)}>
|
||||||
<div
|
<div
|
||||||
className={styles.diamond}
|
className={styles.diamond}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import useLastCallback from '../../../hooks/useLastCallback.ts';
|
|||||||
import styles from './SwayingStar.module.scss';
|
import styles from './SwayingStar.module.scss';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
|
className?: string;
|
||||||
color: 'purple' | 'gold';
|
color: 'purple' | 'gold';
|
||||||
centerShift: readonly [number, number];
|
centerShift: readonly [number, number];
|
||||||
onMouseMove: NoneToVoidFunction;
|
onMouseMove: NoneToVoidFunction;
|
||||||
@ -16,6 +17,7 @@ interface OwnProps {
|
|||||||
const INTERACTIVE_RADIUS = 50;
|
const INTERACTIVE_RADIUS = 50;
|
||||||
|
|
||||||
function SwayingStar({
|
function SwayingStar({
|
||||||
|
className,
|
||||||
color,
|
color,
|
||||||
centerShift,
|
centerShift,
|
||||||
onMouseMove,
|
onMouseMove,
|
||||||
@ -48,7 +50,7 @@ function SwayingStar({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={styles.root}
|
className={buildClassName(styles.root, className)}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -75,8 +75,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.listItem {
|
.listItems {
|
||||||
padding-bottom: 0.5rem;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.listItemTitle {
|
.listItemTitle {
|
||||||
@ -86,5 +88,5 @@
|
|||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
width: calc(100% + 2rem); // Hack to cover modal paddings
|
width: calc(100% + 2rem); // Hack to cover modal paddings
|
||||||
margin-block: 1rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ const TableAboutModal = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{header}
|
{header}
|
||||||
<div>
|
<div className={styles.listItems}>
|
||||||
{listItemData?.map(([icon, title, subtitle]) => {
|
{listItemData?.map(([icon, title, subtitle]) => {
|
||||||
return (
|
return (
|
||||||
<ListItem
|
<ListItem
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
import type { FC } from '../../lib/teact/teact';
|
|
||||||
import type React from '../../lib/teact/teact';
|
|
||||||
|
|
||||||
import buildClassName from '../../util/buildClassName';
|
import buildClassName from '../../util/buildClassName';
|
||||||
|
|
||||||
import useLastCallback from '../../hooks/useLastCallback';
|
import useLastCallback from '../../hooks/useLastCallback';
|
||||||
@ -16,9 +13,9 @@ type OwnProps = {
|
|||||||
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Link: FC<OwnProps> = ({
|
const Link = ({
|
||||||
children, isPrimary, className, isRtl, withMultilineFix, onClick,
|
children, isPrimary, className, isRtl, withMultilineFix, onClick,
|
||||||
}) => {
|
}: OwnProps) => {
|
||||||
const handleClick = useLastCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
|
const handleClick = useLastCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
onClick!(e);
|
onClick!(e);
|
||||||
|
|||||||
@ -161,11 +161,20 @@
|
|||||||
font-weight: var(--font-weight-semibold);
|
font-weight: var(--font-weight-semibold);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.wrap {
|
&.wrap {
|
||||||
display: block;
|
display: block;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.text-only {
|
||||||
|
padding-inline: 0.5rem;
|
||||||
|
line-height: 1.375;
|
||||||
|
}
|
||||||
|
|
||||||
&.menu-custom-emoji-sets {
|
&.menu-custom-emoji-sets {
|
||||||
margin: 0 0.25rem;
|
margin: 0 0.25rem;
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
|
|||||||
@ -91,6 +91,7 @@ const MenuItem = (props: MenuItemProps) => {
|
|||||||
destructive && 'destructive',
|
destructive && 'destructive',
|
||||||
!isTouchScreen && 'compact',
|
!isTouchScreen && 'compact',
|
||||||
withWrap && 'wrap',
|
withWrap && 'wrap',
|
||||||
|
!icon && !customIcon && 'text-only',
|
||||||
);
|
);
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
|
|||||||
@ -345,6 +345,7 @@ export const REPLIES_USER_ID = '1271266957'; // TODO For Test connection ID must
|
|||||||
export const VERIFICATION_CODES_USER_ID = '489000';
|
export const VERIFICATION_CODES_USER_ID = '489000';
|
||||||
export const ANONYMOUS_USER_ID = '2666000';
|
export const ANONYMOUS_USER_ID = '2666000';
|
||||||
export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
|
export const RESTRICTED_EMOJI_SET_ID = '7173162320003080';
|
||||||
|
export const COCOON_EMOJI_ID = '5197252827247841976';
|
||||||
export const LOCAL_MESSAGES_LIMIT = 1e6; // 1M
|
export const LOCAL_MESSAGES_LIMIT = 1e6; // 1M
|
||||||
export const CHANNEL_ID_BASE = 10n ** 12n;
|
export const CHANNEL_ID_BASE = 10n ** 12n;
|
||||||
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
export const DEFAULT_GIF_SEARCH_BOT_USERNAME = 'gif';
|
||||||
|
|||||||
@ -961,3 +961,12 @@ addActionHandler('openQuickChatPicker', (global, actions, payload): ActionReturn
|
|||||||
});
|
});
|
||||||
|
|
||||||
addTabStateResetterAction('closeQuickChatPicker', 'isQuickChatPickerOpen');
|
addTabStateResetterAction('closeQuickChatPicker', 'isQuickChatPickerOpen');
|
||||||
|
|
||||||
|
addActionHandler('openCocoonModal', (global, actions, payload): ActionReturnType => {
|
||||||
|
const { tabId = getCurrentTabId() } = payload || {};
|
||||||
|
return updateTabState(global, {
|
||||||
|
isCocoonModalOpen: true,
|
||||||
|
}, tabId);
|
||||||
|
});
|
||||||
|
|
||||||
|
addTabStateResetterAction('closeCocoonModal', 'isCocoonModalOpen');
|
||||||
|
|||||||
@ -2996,6 +2996,9 @@ export interface ActionPayloads {
|
|||||||
chatId: string;
|
chatId: string;
|
||||||
messageId: number;
|
messageId: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
openCocoonModal: WithTabId | undefined;
|
||||||
|
closeCocoonModal: WithTabId | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RequiredActionPayloads {
|
export interface RequiredActionPayloads {
|
||||||
|
|||||||
@ -975,4 +975,6 @@ export type TabState = {
|
|||||||
isWaitingForStarGiftTransfer?: true;
|
isWaitingForStarGiftTransfer?: true;
|
||||||
insertingPeerIdMention?: string;
|
insertingPeerIdMention?: string;
|
||||||
shouldSaveAttachmentsCompression?: boolean;
|
shouldSaveAttachmentsCompression?: boolean;
|
||||||
|
|
||||||
|
isCocoonModalOpen?: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1872,6 +1872,7 @@ payments.getStarsStatus#4ea9b3bf flags:# ton:flags.0?true peer:InputPeer = payme
|
|||||||
payments.getStarsTransactions#69da4557 flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true ton:flags.4?true subscription_id:flags.3?string peer:InputPeer offset:string limit:int = payments.StarsStatus;
|
payments.getStarsTransactions#69da4557 flags:# inbound:flags.0?true outbound:flags.1?true ascending:flags.2?true ton:flags.4?true subscription_id:flags.3?string peer:InputPeer offset:string limit:int = payments.StarsStatus;
|
||||||
payments.sendStarsForm#7998c914 form_id:long invoice:InputInvoice = payments.PaymentResult;
|
payments.sendStarsForm#7998c914 form_id:long invoice:InputInvoice = payments.PaymentResult;
|
||||||
payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates;
|
payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates;
|
||||||
|
payments.getStarsRevenueStats#d91ffad6 flags:# dark:flags.0?true ton:flags.1?true peer:InputPeer = payments.StarsRevenueStats;
|
||||||
payments.getStarsTransactionsByID#2dca16b8 flags:# ton:flags.0?true peer:InputPeer id:Vector<InputStarsTransaction> = payments.StarsStatus;
|
payments.getStarsTransactionsByID#2dca16b8 flags:# ton:flags.0?true peer:InputPeer id:Vector<InputStarsTransaction> = payments.StarsStatus;
|
||||||
payments.getStarsGiftOptions#d3c96bc8 flags:# user_id:flags.0?InputUser = Vector<StarsGiftOption>;
|
payments.getStarsGiftOptions#d3c96bc8 flags:# user_id:flags.0?InputUser = Vector<StarsGiftOption>;
|
||||||
payments.getStarsSubscriptions#32512c5 flags:# missing_balance:flags.0?true peer:InputPeer offset:string = payments.StarsStatus;
|
payments.getStarsSubscriptions#32512c5 flags:# missing_balance:flags.0?true peer:InputPeer offset:string = payments.StarsStatus;
|
||||||
|
|||||||
@ -331,6 +331,7 @@
|
|||||||
"payments.getStarsTransactions",
|
"payments.getStarsTransactions",
|
||||||
"payments.getStarsTransactionsByID",
|
"payments.getStarsTransactionsByID",
|
||||||
"payments.getStarsSubscriptions",
|
"payments.getStarsSubscriptions",
|
||||||
|
"payments.getStarsRevenueStats",
|
||||||
"payments.changeStarsSubscription",
|
"payments.changeStarsSubscription",
|
||||||
"payments.fulfillStarsSubscription",
|
"payments.fulfillStarsSubscription",
|
||||||
"payments.sendStarsForm",
|
"payments.sendStarsForm",
|
||||||
|
|||||||
25
src/types/language.d.ts
vendored
25
src/types/language.d.ts
vendored
@ -1916,6 +1916,19 @@ export interface LangPair {
|
|||||||
'SettingsDataClearMediaCache': undefined;
|
'SettingsDataClearMediaCache': undefined;
|
||||||
'SettingsDataClearMediaCacheDescription': undefined;
|
'SettingsDataClearMediaCacheDescription': undefined;
|
||||||
'SettingsDataClearMediaDone': undefined;
|
'SettingsDataClearMediaDone': undefined;
|
||||||
|
'TranslateMenuCocoonLinkText': undefined;
|
||||||
|
'CocoonTitle': undefined;
|
||||||
|
'CocoonDescription': undefined;
|
||||||
|
'CocoonFeature1Title': undefined;
|
||||||
|
'CocoonFeature1Username': undefined;
|
||||||
|
'CocoonFeature1UsernameLink': undefined;
|
||||||
|
'CocoonFeature2Title': undefined;
|
||||||
|
'CocoonFeature2Text': undefined;
|
||||||
|
'CocoonFeature3Title': undefined;
|
||||||
|
'CocoonFeature3LinkText': undefined;
|
||||||
|
'CocoonFeature3Link': undefined;
|
||||||
|
'CocoonFooterLinkText': undefined;
|
||||||
|
'CocoonFooterLink': undefined;
|
||||||
'ChatListAuctionWinning': undefined;
|
'ChatListAuctionWinning': undefined;
|
||||||
'ChatListAuctionOutbid': undefined;
|
'ChatListAuctionOutbid': undefined;
|
||||||
'ChatListAuctionView': undefined;
|
'ChatListAuctionView': undefined;
|
||||||
@ -3360,6 +3373,18 @@ export interface LangPairWithVariables<V = LangVariable> {
|
|||||||
'status': V;
|
'status': V;
|
||||||
'onlineCount': V;
|
'onlineCount': V;
|
||||||
};
|
};
|
||||||
|
'TranslateMenuCocoon': {
|
||||||
|
'link': V;
|
||||||
|
};
|
||||||
|
'CocoonFeature1Text': {
|
||||||
|
'username': V;
|
||||||
|
};
|
||||||
|
'CocoonFeature3Text': {
|
||||||
|
'link': V;
|
||||||
|
};
|
||||||
|
'CocoonFooterText': {
|
||||||
|
'link': V;
|
||||||
|
};
|
||||||
'ChatListAuctionMixed': {
|
'ChatListAuctionMixed': {
|
||||||
'winCount': V;
|
'winCount': V;
|
||||||
'outbidCount': V;
|
'outbidCount': V;
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
import type React from '../lib/teact/teact';
|
|
||||||
|
|
||||||
const stopEvent = (e: React.UIEvent | Event | React.FormEvent) => {
|
const stopEvent = (e: React.UIEvent | Event | React.FormEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@ -164,7 +164,7 @@ export default function createConfig(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(woff(2)?|ttf|eot|svg|png|jpg|tgs)(\?v=\d+\.\d+\.\d+)?$/,
|
test: /\.(woff(2)?|ttf|eot|svg|png|jpg|tgs|webp)(\?v=\d+\.\d+\.\d+)?$/,
|
||||||
type: 'asset/resource',
|
type: 'asset/resource',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user