Management: Fix layout in management boost list (#4645)
This commit is contained in:
parent
1997008ba5
commit
86ddd5bf0b
@ -12,17 +12,13 @@
|
||||
}
|
||||
|
||||
.badgeContainer {
|
||||
--min-shift: calc(10% + var(--digits-count, 1) * 0.4ch);
|
||||
--max-shift: calc(85% - var(--digits-count, 1) * 0.4ch);
|
||||
--shift-x: calc(clamp(var(--min-shift), var(--percent), var(--max-shift)) - 50%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
top: -1.5rem;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translate(var(--shift-x), -20px);
|
||||
|
||||
transform: translate(calc(var(--shift-x) * 100% - 50%), -20px);
|
||||
transition: transform 0.2s ease-in-out;
|
||||
animation: slide-in 0.5s ease-in-out;
|
||||
}
|
||||
@ -33,7 +29,7 @@
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate(var(--shift-x), -20px);
|
||||
transform: translate(calc(var(--shift-x) * 100% - 50%), -20px);
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +71,7 @@
|
||||
.floating-badge-triangle {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
bottom: -5px;
|
||||
bottom: -4px;
|
||||
left: calc(var(--tail-position, 0.5) * 100%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { memo } from '../../lib/teact/teact';
|
||||
import React, {
|
||||
memo, useEffect, useRef, useState,
|
||||
} from '../../lib/teact/teact';
|
||||
|
||||
import type { IconName } from '../../types/icons';
|
||||
|
||||
@ -7,6 +9,7 @@ import buildClassName from '../../util/buildClassName';
|
||||
import buildStyle from '../../util/buildStyle';
|
||||
|
||||
import useLang from '../../hooks/useLang';
|
||||
import useResizeObserver from '../../hooks/useResizeObserver';
|
||||
|
||||
import Icon from './Icon';
|
||||
|
||||
@ -21,8 +24,6 @@ type OwnProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const PROGRESS_LOCK = 0.1;
|
||||
|
||||
const LimitPreview: FC<OwnProps> = ({
|
||||
leftText,
|
||||
rightText,
|
||||
@ -32,15 +33,48 @@ const LimitPreview: FC<OwnProps> = ({
|
||||
className,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const floatingBadgeRef = useRef<HTMLDivElement>(null);
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const parentContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [shiftX, setShiftX] = useState(0);
|
||||
const [tailPosition, setTailPosition] = useState(0);
|
||||
|
||||
const updateBadgePosition = () => {
|
||||
if (floatingBadgeRef.current && parentContainerRef.current && progress !== undefined) {
|
||||
const badgeWidth = floatingBadgeRef.current.offsetWidth;
|
||||
const parentWidth = parentContainerRef.current.offsetWidth;
|
||||
const minShift = badgeWidth / 2;
|
||||
const maxShift = parentWidth - badgeWidth / 2;
|
||||
const currentShift = progress * parentWidth;
|
||||
const safeShift = Math.max(minShift, Math.min(currentShift, maxShift));
|
||||
|
||||
setShiftX(safeShift / parentWidth);
|
||||
|
||||
let newTailPosition;
|
||||
if (currentShift < minShift) {
|
||||
newTailPosition = (progress * parentWidth) / (minShift * 2);
|
||||
} else if (currentShift > maxShift) {
|
||||
const progressMapped = (progress - (maxShift / parentWidth)) / (1 - maxShift / parentWidth);
|
||||
newTailPosition = 0.5 + (progressMapped * 0.4);
|
||||
} else {
|
||||
newTailPosition = 0.5;
|
||||
}
|
||||
setTailPosition(newTailPosition);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(updateBadgePosition, [progress]);
|
||||
|
||||
useResizeObserver(parentContainerRef, updateBadgePosition);
|
||||
|
||||
const hasFloatingBadge = Boolean(floatingBadgeIcon || floatingBadgeText);
|
||||
const isProgressFull = Boolean(progress) && progress > 0.99;
|
||||
const digitsCount = floatingBadgeText?.length;
|
||||
|
||||
const tailPosition = progress && (progress < PROGRESS_LOCK ? 0 : progress > 1 - PROGRESS_LOCK ? 1 : 0.5);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={parentContainerRef}
|
||||
className={buildClassName(
|
||||
styles.root,
|
||||
hasFloatingBadge && styles.withBadge,
|
||||
@ -49,13 +83,13 @@ const LimitPreview: FC<OwnProps> = ({
|
||||
style={buildStyle(
|
||||
progress !== undefined && `--progress: ${progress}`,
|
||||
tailPosition !== undefined && `--tail-position: ${tailPosition}`,
|
||||
digitsCount !== undefined && `--digits-count: ${digitsCount}`,
|
||||
`--shift-x: ${shiftX}`,
|
||||
)}
|
||||
>
|
||||
{hasFloatingBadge && (
|
||||
<div className={styles.badgeContainer}>
|
||||
<div className={styles.floatingBadgeWrapper}>
|
||||
<div className={styles.floatingBadge}>
|
||||
<div className={styles.floatingBadge} ref={floatingBadgeRef}>
|
||||
{floatingBadgeIcon && <Icon name={floatingBadgeIcon} className={styles.floatingBadgeIcon} />}
|
||||
{floatingBadgeText && (
|
||||
<div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
.status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
gap: 0.5rem;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
@ -111,3 +111,8 @@
|
||||
.giveawayButton {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.giveawayIcon {
|
||||
width: 2.75rem;
|
||||
height: 2.75rem;
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ const BoostStatistics = ({
|
||||
>
|
||||
<Icon name="gift" className={styles.floatingBadgeIcon} />
|
||||
<div className={styles.floatingBadgeValue}>{lang(boost.isFromGiveaway
|
||||
? 'lng_prizes_results_link' : 'BoostingGift')}
|
||||
? 'BoostingGiveaway' : 'BoostingGift')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -218,11 +218,13 @@ const BoostStatistics = ({
|
||||
);
|
||||
});
|
||||
|
||||
const handleGiveawayClick = useLastCallback(() => {
|
||||
const handleGiveawayClick = useLastCallback((e) => {
|
||||
e.preventDefault();
|
||||
openGiveawayModal({ chatId });
|
||||
});
|
||||
|
||||
const handleLoadMore = useLastCallback(() => {
|
||||
const handleLoadMore = useLastCallback((e) => {
|
||||
e.preventDefault();
|
||||
loadMoreBoosters({ isGifts: tabType === 'giftedBoostList' });
|
||||
});
|
||||
|
||||
@ -243,7 +245,7 @@ const BoostStatistics = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<div className={styles.section}>
|
||||
{listToRender?.map((boost) => renderBoostList(boost))}
|
||||
</div>
|
||||
);
|
||||
@ -278,7 +280,11 @@ const BoostStatistics = ({
|
||||
>
|
||||
<div className={buildClassName(styles.status, 'status-clickable')}>
|
||||
<div>
|
||||
<img src={GIVEAWAY_IMG_LIST[prepaidGiveaway.months]} alt="Giveaway" />
|
||||
<img
|
||||
src={GIVEAWAY_IMG_LIST[prepaidGiveaway.months]}
|
||||
className={styles.giveawayIcon}
|
||||
alt={lang('Giveaway')}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.info}>
|
||||
<h3>
|
||||
@ -303,13 +309,12 @@ const BoostStatistics = ({
|
||||
<p className="text-muted hint" key="links-hint">{lang('BoostingSelectPaidGiveaway')}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.section}>
|
||||
<div>
|
||||
{shouldDisplayGiftList ? (
|
||||
<div
|
||||
className={styles.boostSection}
|
||||
className={buildClassName(styles.boostSection, styles.content)}
|
||||
>
|
||||
<Transition
|
||||
key={activeKey}
|
||||
ref={transitionRef}
|
||||
name={lang.isRtl ? 'slideOptimizedRtl' : 'slideOptimized'}
|
||||
activeKey={activeKey}
|
||||
@ -322,7 +327,7 @@ const BoostStatistics = ({
|
||||
<TabList big activeTab={renderingActiveTab} tabs={tabs} onSwitchTab={setActiveTab} />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className={styles.section}>
|
||||
<h4 className={styles.sectionHeader} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('BoostingBoostsCount', boostStatistics?.boosts?.count)}
|
||||
</h4>
|
||||
@ -331,28 +336,35 @@ const BoostStatistics = ({
|
||||
</div>
|
||||
)}
|
||||
{boostStatistics?.boosts?.list?.map((boost) => renderBoostList(boost))}
|
||||
</>
|
||||
)}
|
||||
{Boolean(boostersToLoadCount) && (
|
||||
<ListItem
|
||||
key="load-more"
|
||||
className={styles.showMore}
|
||||
disabled={boostStatistics?.isLoadingBoosters}
|
||||
onClick={handleLoadMore}
|
||||
>
|
||||
{boostStatistics?.isLoadingBoosters ? (
|
||||
<Spinner className={styles.loadMoreSpinner} />
|
||||
) : (
|
||||
<Icon name="down" className={styles.down} />
|
||||
)}
|
||||
{lang('ShowVotes', boostersToLoadCount, 'i')}
|
||||
</ListItem>
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.section}>
|
||||
{Boolean(boostersToLoadCount) && (
|
||||
<ListItem
|
||||
key="load-more"
|
||||
className={styles.showMore}
|
||||
disabled={boostStatistics?.isLoadingBoosters}
|
||||
onClick={handleLoadMore}
|
||||
>
|
||||
{boostStatistics?.isLoadingBoosters ? (
|
||||
<Spinner className={styles.loadMoreSpinner} />
|
||||
) : (
|
||||
<Icon name="down" className={styles.down} />
|
||||
)}
|
||||
{lang('ShowVotes', boostersToLoadCount, 'i')}
|
||||
</ListItem>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<LinkField className={styles.section} link={status!.boostUrl} withShare title={lang('LinkForBoosting')} />
|
||||
{isGiveawayAvailable && (
|
||||
<div className={styles.section}>
|
||||
<ListItem icon="gift" ripple onClick={handleGiveawayClick} className={styles.giveawayButton}>
|
||||
<ListItem
|
||||
key="load-more"
|
||||
icon="gift"
|
||||
onClick={handleGiveawayClick}
|
||||
className={styles.giveawayButton}
|
||||
>
|
||||
{lang('BoostingGetBoostsViaGifts')}
|
||||
</ListItem>
|
||||
<p className="text-muted hint" key="links-hint">{lang(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user