Add drawer subtitle (ex view count for livestreams)
This commit is contained in:
parent
3a511d0647
commit
0399250906
4 changed files with 67 additions and 12 deletions
|
@ -3,15 +3,20 @@ import { selectClaimForUri, makeSelectTagInClaimOrChannelForUri, selectThumbnail
|
||||||
import { selectSuperChatsForUri } from 'redux/selectors/comments';
|
import { selectSuperChatsForUri } from 'redux/selectors/comments';
|
||||||
import LivestreamLayout from './view';
|
import LivestreamLayout from './view';
|
||||||
import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
import { DISABLE_COMMENTS_TAG } from 'constants/tags';
|
||||||
|
import { selectViewersForId } from 'redux/selectors/livestream';
|
||||||
|
|
||||||
const select = (state, props) => {
|
const select = (state, props) => {
|
||||||
const { uri } = props;
|
const { uri } = props;
|
||||||
|
|
||||||
|
const claim = selectClaimForUri(state, uri);
|
||||||
|
const claimId = claim && claim.claim_id;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
claim: selectClaimForUri(state, uri),
|
claim,
|
||||||
thumbnail: selectThumbnailForUri(state, uri),
|
thumbnail: selectThumbnailForUri(state, uri),
|
||||||
chatDisabled: makeSelectTagInClaimOrChannelForUri(uri, DISABLE_COMMENTS_TAG)(state),
|
chatDisabled: makeSelectTagInClaimOrChannelForUri(uri, DISABLE_COMMENTS_TAG)(state),
|
||||||
superChats: selectSuperChatsForUri(state, uri),
|
superChats: selectSuperChatsForUri(state, uri),
|
||||||
|
activeViewers: claimId && selectViewersForId(state, claimId),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ type Props = {
|
||||||
showScheduledInfo: boolean,
|
showScheduledInfo: boolean,
|
||||||
uri: string,
|
uri: string,
|
||||||
superChats: Array<Comment>,
|
superChats: Array<Comment>,
|
||||||
|
activeViewers?: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function LivestreamLayout(props: Props) {
|
export default function LivestreamLayout(props: Props) {
|
||||||
|
@ -48,6 +49,7 @@ export default function LivestreamLayout(props: Props) {
|
||||||
showScheduledInfo,
|
showScheduledInfo,
|
||||||
uri,
|
uri,
|
||||||
superChats,
|
superChats,
|
||||||
|
activeViewers,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
|
@ -114,8 +116,10 @@ export default function LivestreamLayout(props: Props) {
|
||||||
superChats={superChats}
|
superChats={superChats}
|
||||||
chatViewMode={chatViewMode}
|
chatViewMode={chatViewMode}
|
||||||
setChatViewMode={(mode) => setChatViewMode(mode)}
|
setChatViewMode={(mode) => setChatViewMode(mode)}
|
||||||
|
activeViewers={activeViewers}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
hasSubtitle={activeViewers}
|
||||||
actions={
|
actions={
|
||||||
<LivestreamMenu
|
<LivestreamMenu
|
||||||
noSuperchats={!superChats || superChats.length === 0}
|
noSuperchats={!superChats || superChats.length === 0}
|
||||||
|
@ -145,20 +149,23 @@ export default function LivestreamLayout(props: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChatModeSelector = (chatSelectorProps: any) => {
|
const ChatModeSelector = (chatSelectorProps: any) => {
|
||||||
const { superChats, chatViewMode, setChatViewMode } = chatSelectorProps;
|
const { superChats, chatViewMode, setChatViewMode, activeViewers } = chatSelectorProps;
|
||||||
const { superChatsFiatAmount, superChatsLBCAmount } = getTipValues(superChats);
|
const { superChatsFiatAmount, superChatsLBCAmount } = getTipValues(superChats);
|
||||||
|
|
||||||
|
const titleProps = { chatViewMode, activeViewers };
|
||||||
|
|
||||||
if (!superChats) {
|
if (!superChats) {
|
||||||
return __('Live Chat');
|
return <ChatDrawerTitle {...titleProps} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu>
|
<Menu>
|
||||||
<MenuButton>
|
<MenuButton>
|
||||||
<span className="swipeable-drawer__title-menu">
|
<div className="swipeable-drawer__menu">
|
||||||
{chatViewMode === VIEW_MODES.CHAT ? __('Live Chat') : __('HyperChats')}
|
<ChatDrawerTitle {...titleProps} />
|
||||||
|
|
||||||
<Icon icon={ICONS.DOWN} />
|
<Icon icon={ICONS.DOWN} />
|
||||||
</span>
|
</div>
|
||||||
</MenuButton>
|
</MenuButton>
|
||||||
|
|
||||||
<MenuList className="menu__list--header">
|
<MenuList className="menu__list--header">
|
||||||
|
@ -176,3 +183,19 @@ const ChatModeSelector = (chatSelectorProps: any) => {
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ChatDrawerTitle = (titleProps: any) => {
|
||||||
|
const { chatViewMode, activeViewers } = titleProps;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="swipeable-drawer__title-menu">
|
||||||
|
<span className="swipeable-drawer__title">
|
||||||
|
{chatViewMode === VIEW_MODES.CHAT ? __('Live Chat') : __('HyperChats')}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{activeViewers && (
|
||||||
|
<span className="swipeable-drawer__subtitle">{__('%view_count% viewers', { view_count: activeViewers })}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { SwipeableDrawer as MUIDrawer } from '@mui/material';
|
||||||
import * as ICONS from 'constants/icons';
|
import * as ICONS from 'constants/icons';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
const DRAWER_PULLER_HEIGHT = 42;
|
const DRAWER_PULLER_HEIGHT = 42;
|
||||||
|
|
||||||
|
@ -20,12 +21,13 @@ type Props = {
|
||||||
theme: string,
|
theme: string,
|
||||||
mobilePlayerDimensions?: { height: number },
|
mobilePlayerDimensions?: { height: number },
|
||||||
title: any,
|
title: any,
|
||||||
|
hasSubtitle?: boolean,
|
||||||
actions?: any,
|
actions?: any,
|
||||||
toggleDrawer: () => void,
|
toggleDrawer: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SwipeableDrawer(props: Props) {
|
export default function SwipeableDrawer(props: Props) {
|
||||||
const { mobilePlayerDimensions, title, children, open, theme, actions, toggleDrawer } = props;
|
const { mobilePlayerDimensions, title, hasSubtitle, children, open, theme, actions, toggleDrawer } = props;
|
||||||
|
|
||||||
const [coverHeight, setCoverHeight] = React.useState();
|
const [coverHeight, setCoverHeight] = React.useState();
|
||||||
|
|
||||||
|
@ -69,7 +71,7 @@ export default function SwipeableDrawer(props: Props) {
|
||||||
{open && (
|
{open && (
|
||||||
<div className="swipeable-drawer__header" style={{ top: -DRAWER_PULLER_HEIGHT }}>
|
<div className="swipeable-drawer__header" style={{ top: -DRAWER_PULLER_HEIGHT }}>
|
||||||
<Puller theme={theme} />
|
<Puller theme={theme} />
|
||||||
<HeaderContents title={title} actions={actions} toggleDrawer={toggleDrawer} />
|
<HeaderContents title={title} hasSubtitle={hasSubtitle} actions={actions} toggleDrawer={toggleDrawer} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -122,15 +124,20 @@ const Puller = (pullerProps: PullerProps) => {
|
||||||
|
|
||||||
type HeaderProps = {
|
type HeaderProps = {
|
||||||
title: any,
|
title: any,
|
||||||
|
hasSubtitle?: boolean,
|
||||||
actions?: any,
|
actions?: any,
|
||||||
toggleDrawer: () => void,
|
toggleDrawer: () => void,
|
||||||
};
|
};
|
||||||
|
|
||||||
const HeaderContents = (headerProps: HeaderProps) => {
|
const HeaderContents = (headerProps: HeaderProps) => {
|
||||||
const { title, actions, toggleDrawer } = headerProps;
|
const { title, hasSubtitle, actions, toggleDrawer } = headerProps;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="swipeable-drawer__header-content">
|
<div
|
||||||
|
className={classnames('swipeable-drawer__header-content', {
|
||||||
|
'swipeable-drawer__header--with-subtitle': hasSubtitle,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{title}
|
{title}
|
||||||
|
|
||||||
<div className="swipeable-drawer__header-actions">
|
<div className="swipeable-drawer__header-actions">
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
right: 2px !important;
|
right: 2px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span,
|
||||||
|
svg {
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +33,11 @@
|
||||||
font-size: var(--font-small);
|
font-size: var(--font-small);
|
||||||
}
|
}
|
||||||
|
|
||||||
.swipeable-drawer__title-menu {
|
.swipeable-drawer__header--with-subtitle {
|
||||||
|
padding: var(--spacing-xxs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swipeable-drawer__menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
|
@ -41,6 +46,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.swipeable-drawer__title-menu {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.swipeable-drawer__title {
|
||||||
|
font-size: var(--font-xsmall);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swipeable-drawer__subtitle {
|
||||||
|
font-size: var(--font-xxsmall);
|
||||||
|
color: var(--color-text-subtitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.swipeable-drawer__header-actions {
|
.swipeable-drawer__header-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue