228 lines
6.3 KiB
TypeScript
228 lines
6.3 KiB
TypeScript
import type { FC } from '../../../lib/teact/teact';
|
|
import React, {
|
|
memo, useEffect, useMemo, useRef,
|
|
useState,
|
|
} from '../../../lib/teact/teact';
|
|
import { getActions, getGlobal, withGlobal } from '../../../global';
|
|
|
|
import type {
|
|
ApiStarTopupOption, ApiUser,
|
|
} from '../../../api/types';
|
|
|
|
import { getSenderTitle } from '../../../global/helpers';
|
|
import {
|
|
selectTabState, selectUser,
|
|
} from '../../../global/selectors';
|
|
import buildClassName from '../../../util/buildClassName';
|
|
import { formatCurrencyAsString } from '../../../util/formatCurrency';
|
|
import renderText from '../../common/helpers/renderText';
|
|
|
|
import useLastCallback from '../../../hooks/useLastCallback';
|
|
import useOldLang from '../../../hooks/useOldLang';
|
|
|
|
import Avatar from '../../common/Avatar';
|
|
import SafeLink from '../../common/SafeLink';
|
|
import StarTopupOptionList from '../../modals/stars/StarTopupOptionList';
|
|
import Button from '../../ui/Button';
|
|
import Modal from '../../ui/Modal';
|
|
|
|
import styles from './StarsGiftModal.module.scss';
|
|
|
|
import StarLogo from '../../../assets/icons/StarLogo.svg';
|
|
import StarsBackground from '../../../assets/stars-bg.png';
|
|
|
|
export type OwnProps = {
|
|
isOpen?: boolean;
|
|
};
|
|
|
|
type StateProps = {
|
|
isCompleted?: boolean;
|
|
starsGiftOptions?: ApiStarTopupOption[] | undefined;
|
|
forUserId?: string;
|
|
user?: ApiUser;
|
|
};
|
|
|
|
const StarsGiftModal: FC<OwnProps & StateProps> = ({
|
|
isOpen,
|
|
isCompleted,
|
|
starsGiftOptions,
|
|
forUserId,
|
|
user,
|
|
}) => {
|
|
// eslint-disable-next-line no-null/no-null
|
|
const dialogRef = useRef<HTMLDivElement>(null);
|
|
|
|
const {
|
|
closeStarsGiftModal, openInvoice, requestConfetti,
|
|
} = getActions();
|
|
|
|
const oldLang = useOldLang();
|
|
|
|
const [selectedOption, setSelectedOption] = useState<ApiStarTopupOption | undefined>();
|
|
const [isHeaderHidden, setHeaderHidden] = useState(true);
|
|
|
|
useEffect(() => {
|
|
if (!isOpen) {
|
|
setHeaderHidden(true);
|
|
}
|
|
}, [isOpen]);
|
|
|
|
const showConfetti = useLastCallback(() => {
|
|
const dialog = dialogRef.current;
|
|
if (!dialog) return;
|
|
if (isOpen) {
|
|
const {
|
|
top, left, width, height,
|
|
} = dialog.querySelector('.modal-content')!.getBoundingClientRect();
|
|
requestConfetti({
|
|
top,
|
|
left,
|
|
width,
|
|
height,
|
|
withStars: true,
|
|
});
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (isCompleted) {
|
|
showConfetti();
|
|
}
|
|
}, [isCompleted, showConfetti]);
|
|
|
|
const handleClick = useLastCallback((option: ApiStarTopupOption) => {
|
|
setSelectedOption(option);
|
|
if (user) {
|
|
openInvoice({
|
|
type: 'starsgift',
|
|
userId: forUserId!,
|
|
stars: option.stars,
|
|
currency: option.currency,
|
|
amount: option.amount,
|
|
});
|
|
} else {
|
|
openInvoice({
|
|
type: 'stars',
|
|
stars: option.stars,
|
|
currency: option.currency,
|
|
amount: option.amount,
|
|
});
|
|
}
|
|
});
|
|
|
|
function handleScroll(e: React.UIEvent<HTMLDivElement>) {
|
|
const { scrollTop } = e.currentTarget;
|
|
|
|
setHeaderHidden(scrollTop <= 150);
|
|
}
|
|
|
|
const handleClose = useLastCallback(() => {
|
|
closeStarsGiftModal();
|
|
});
|
|
|
|
function renderGiftTitle() {
|
|
if (isCompleted) {
|
|
return user ? renderText(oldLang('Notification.StarsGift.SentYou',
|
|
formatCurrencyAsString(selectedOption!.amount, selectedOption!.currency, oldLang.code)), ['simple_markdown'])
|
|
: renderText(oldLang('StarsAcquiredInfo', selectedOption?.stars), ['simple_markdown']);
|
|
}
|
|
|
|
return user ? oldLang('GiftStarsTitle') : oldLang('Star.List.GetStars');
|
|
}
|
|
|
|
function renderStarOptionList() {
|
|
return (
|
|
<StarTopupOptionList
|
|
options={starsGiftOptions}
|
|
onClick={handleClick}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const bottomText = useMemo(() => {
|
|
if (!isOpen) return undefined;
|
|
|
|
const text = oldLang('lng_credits_summary_options_about');
|
|
const parts = text.split('{link}');
|
|
return [
|
|
parts[0],
|
|
<SafeLink url={oldLang('StarsTOSLink')} text={oldLang('lng_credits_summary_options_about_link')} />,
|
|
parts[1],
|
|
];
|
|
}, [isOpen, oldLang]);
|
|
|
|
return (
|
|
<Modal
|
|
className={buildClassName(styles.modalDialog, styles.root)}
|
|
dialogRef={dialogRef}
|
|
onClose={handleClose}
|
|
isOpen={isOpen}
|
|
>
|
|
<div className={styles.main} onScroll={handleScroll}>
|
|
<Button
|
|
round
|
|
size="smaller"
|
|
className={styles.closeButton}
|
|
color="translucent"
|
|
// eslint-disable-next-line react/jsx-no-bind
|
|
onClick={() => closeStarsGiftModal()}
|
|
ariaLabel={oldLang('Close')}
|
|
>
|
|
<i className="icon icon-close" />
|
|
</Button>
|
|
<div className={buildClassName(styles.header, isHeaderHidden && styles.hiddenHeader)}>
|
|
<h2 className={styles.starHeaderText}>
|
|
{user ? oldLang('GiftStarsTitle') : oldLang('Star.List.GetStars')}
|
|
</h2>
|
|
</div>
|
|
<div className={styles.headerInfo}>
|
|
{user ? (
|
|
<>
|
|
<Avatar
|
|
size="huge"
|
|
peer={user}
|
|
className={styles.avatar}
|
|
/>
|
|
<img className={styles.logoBackground} src={StarsBackground} alt="" draggable={false} />
|
|
</>
|
|
) : (
|
|
<>
|
|
<img className={styles.logo} src={StarLogo} alt="" draggable={false} />
|
|
<img className={styles.logoBackground} src={StarsBackground} alt="" draggable={false} />
|
|
</>
|
|
)}
|
|
</div>
|
|
<h2 className={buildClassName(styles.headerText, styles.center)}>
|
|
{renderGiftTitle()}
|
|
</h2>
|
|
<p className={styles.description}>
|
|
{user ? renderText(
|
|
oldLang('ActionGiftStarsSubtitle', getSenderTitle(oldLang, user)), ['simple_markdown'],
|
|
) : oldLang('Stars.Purchase.GetStarsInfo')}
|
|
</p>
|
|
<div className={styles.section}>
|
|
{renderStarOptionList()}
|
|
<div className={styles.secondaryInfo}>
|
|
{bottomText}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default memo(withGlobal<OwnProps>((global): StateProps => {
|
|
const {
|
|
starsGiftOptions, forUserId, isCompleted,
|
|
} = selectTabState(global).starsGiftModal || {};
|
|
|
|
const user = forUserId ? selectUser(getGlobal(), forUserId) : undefined;
|
|
|
|
return {
|
|
isCompleted,
|
|
starsGiftOptions,
|
|
forUserId,
|
|
user,
|
|
};
|
|
})(StarsGiftModal));
|