Story: Display forwards count in channels (#4092)

This commit is contained in:
Alexander Zinchuk 2023-12-12 12:34:36 +01:00
parent b4291a1505
commit 2edd680802
6 changed files with 73 additions and 38 deletions

View File

@ -68,6 +68,7 @@ export function buildApiStory(peerId: string, story: GramJs.TypeStoryItem): ApiT
...(closeFriends && { isForCloseFriends: true }), ...(closeFriends && { isForCloseFriends: true }),
...(noforwards && { noForwards: true }), ...(noforwards && { noForwards: true }),
...(views?.viewsCount && { viewsCount: views.viewsCount }), ...(views?.viewsCount && { viewsCount: views.viewsCount }),
...(views?.forwardsCount && { forwardsCount: views.forwardsCount }),
...(views?.reactionsCount && { reactionsCount: views.reactionsCount }), ...(views?.reactionsCount && { reactionsCount: views.reactionsCount }),
...(views?.reactions && { reactions: views.reactions.map(buildReactionCount) }), ...(views?.reactions && { reactions: views.reactions.map(buildReactionCount) }),
...(views?.recentViewers && { ...(views?.recentViewers && {

View File

@ -19,6 +19,7 @@ export interface ApiStory {
isOut?: true; isOut?: true;
noForwards?: boolean; noForwards?: boolean;
viewsCount?: number; viewsCount?: number;
forwardsCount?: number;
reactionsCount?: number; reactionsCount?: number;
reactions?: ApiReactionCount[]; reactions?: ApiReactionCount[];
recentViewerIds?: string[]; recentViewerIds?: string[];

View File

@ -53,10 +53,17 @@
font-size: 1.25rem; font-size: 1.25rem;
} }
.channelReaction { .footerItem {
display: flex; display: flex;
align-items: center; align-items: center;
padding-inline-end: 0.5rem;
&:last-child {
padding-inline-end: 0.5rem;
}
& + & {
margin-inline-end: 0.5rem;
}
} }
.views { .views {

View File

@ -32,7 +32,7 @@ const StoryFooter = ({
const lang = useLang(); const lang = useLang();
const { const {
viewsCount, reactionsCount, isOut, peerId, id: storyId, sentReaction, viewsCount, forwardsCount, reactionsCount, isOut, peerId, id: storyId, sentReaction,
} = story; } = story;
const isChannel = !isUserId(peerId); const isChannel = !isUserId(peerId);
@ -121,37 +121,54 @@ const StoryFooter = ({
round round
onClick={handleForwardClick} onClick={handleForwardClick}
ariaLabel={lang('Forward')} ariaLabel={lang('Forward')}
className={styles.footerItem}
> >
<Icon name="forward" /> <Icon name="forward" />
</Button> </Button>
)} )}
{isChannel && ( {isChannel && (
<div className={styles.channelReaction}> <>
<Button {Boolean(forwardsCount) && (
round <div className={styles.footerItem}>
className={styles.reactionButton} <Button
color="translucent" round
size="smaller" color="translucent"
onClick={handleLikeStory} size="smaller"
ariaLabel={lang('AccDescrLike')} nonInteractive
> ariaLabel={lang('PublicShares')}
{sentReaction && ( >
<ReactionAnimatedEmoji <Icon name="loop" />
key={'documentId' in sentReaction ? sentReaction.documentId : sentReaction.emoticon} </Button>
containerId={containerId} <span>{forwardsCount}</span>
reaction={sentReaction} </div>
withEffectOnly={isSentStoryReactionHeart} )}
/> <div className={styles.footerItem}>
)} <Button
{(!sentReaction || isSentStoryReactionHeart) && ( round
<Icon className={styles.reactionButton}
name={isSentStoryReactionHeart ? 'heart' : 'heart-outline'} color="translucent"
className={buildClassName(isSentStoryReactionHeart && styles.reactionHeart)} size="smaller"
/> onClick={handleLikeStory}
)} ariaLabel={lang('AccDescrLike')}
</Button> >
{Boolean(reactionsCount) && (<span>{reactionsCount}</span>)} {sentReaction && (
</div> <ReactionAnimatedEmoji
key={'documentId' in sentReaction ? sentReaction.documentId : sentReaction.emoticon}
containerId={containerId}
reaction={sentReaction}
withEffectOnly={isSentStoryReactionHeart}
/>
)}
{(!sentReaction || isSentStoryReactionHeart) && (
<Icon
name={isSentStoryReactionHeart ? 'heart' : 'heart-outline'}
className={buildClassName(isSentStoryReactionHeart && styles.reactionHeart)}
/>
)}
</Button>
{Boolean(reactionsCount) && (<span>{reactionsCount}</span>)}
</div>
</>
)} )}
</div> </div>
); );

View File

@ -55,8 +55,12 @@
} }
&.disabled { &.disabled {
opacity: 0.5 !important;
cursor: var(--custom-cursor, default); cursor: var(--custom-cursor, default);
&:not(.non-interactive) {
opacity: 0.5 !important;
}
&:not(.click-allowed) { &:not(.click-allowed) {
pointer-events: none; pointer-events: none;
} }

View File

@ -36,6 +36,7 @@ export type OwnProps = {
href?: string; href?: string;
download?: string; download?: string;
disabled?: boolean; disabled?: boolean;
nonInteractive?: boolean;
allowDisabledClick?: boolean; allowDisabledClick?: boolean;
noFastClick?: boolean; noFastClick?: boolean;
ripple?: boolean; ripple?: boolean;
@ -91,6 +92,7 @@ const Button: FC<OwnProps> = ({
href, href,
download, download,
disabled, disabled,
nonInteractive,
allowDisabledClick, allowDisabledClick,
noFastClick = color === 'danger', noFastClick = color === 'danger',
ripple, ripple,
@ -110,6 +112,8 @@ const Button: FC<OwnProps> = ({
const [isClicked, setIsClicked] = useState(false); const [isClicked, setIsClicked] = useState(false);
const isNotInteractive = disabled || nonInteractive;
const fullClassName = buildClassName( const fullClassName = buildClassName(
'Button', 'Button',
className, className,
@ -118,7 +122,8 @@ const Button: FC<OwnProps> = ({
round && 'round', round && 'round',
pill && 'pill', pill && 'pill',
fluid && 'fluid', fluid && 'fluid',
disabled && 'disabled', isNotInteractive && 'disabled',
nonInteractive && 'non-interactive',
allowDisabledClick && 'click-allowed', allowDisabledClick && 'click-allowed',
isText && 'text', isText && 'text',
isLoading && 'loading', isLoading && 'loading',
@ -132,7 +137,7 @@ const Button: FC<OwnProps> = ({
); );
const handleClick = useLastCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => { const handleClick = useLastCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
if ((allowDisabledClick || !disabled) && onClick) { if ((allowDisabledClick || !isNotInteractive) && onClick) {
onClick(e); onClick(e);
} }
@ -147,7 +152,7 @@ const Button: FC<OwnProps> = ({
const handleMouseDown = useLastCallback((e: ReactMouseEvent<HTMLButtonElement>) => { const handleMouseDown = useLastCallback((e: ReactMouseEvent<HTMLButtonElement>) => {
if (!noPreventDefault) e.preventDefault(); if (!noPreventDefault) e.preventDefault();
if ((allowDisabledClick || !disabled) && onMouseDown) { if ((allowDisabledClick || !isNotInteractive) && onMouseDown) {
onMouseDown(e); onMouseDown(e);
} }
@ -173,7 +178,7 @@ const Button: FC<OwnProps> = ({
onTransitionEnd={onTransitionEnd} onTransitionEnd={onTransitionEnd}
> >
{children} {children}
{!disabled && ripple && ( {!isNotInteractive && ripple && (
<RippleEffect /> <RippleEffect />
)} )}
</a> </a>
@ -190,10 +195,10 @@ const Button: FC<OwnProps> = ({
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
onMouseUp={onMouseUp} onMouseUp={onMouseUp}
onMouseEnter={onMouseEnter && !disabled ? onMouseEnter : undefined} onMouseEnter={onMouseEnter && !isNotInteractive ? onMouseEnter : undefined}
onMouseLeave={onMouseLeave && !disabled ? onMouseLeave : undefined} onMouseLeave={onMouseLeave && !isNotInteractive ? onMouseLeave : undefined}
onTransitionEnd={onTransitionEnd} onTransitionEnd={onTransitionEnd}
onFocus={onFocus && !disabled ? onFocus : undefined} onFocus={onFocus && !isNotInteractive ? onFocus : undefined}
aria-label={ariaLabel} aria-label={ariaLabel}
aria-controls={ariaControls} aria-controls={ariaControls}
aria-haspopup={hasPopup} aria-haspopup={hasPopup}
@ -208,7 +213,7 @@ const Button: FC<OwnProps> = ({
<Spinner color={isText ? 'blue' : 'white'} /> <Spinner color={isText ? 'blue' : 'white'} />
</div> </div>
) : children} ) : children}
{!disabled && ripple && ( {!isNotInteractive && ripple && (
<RippleEffect /> <RippleEffect />
)} )}
</button> </button>