Limit to 10 superchats initially; batch-resolve when opening full list.

This commit is contained in:
infinite-persistence 2021-11-04 16:01:29 +08:00
parent a65e68d023
commit 17903f6c15
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
3 changed files with 70 additions and 6 deletions

View file

@ -1,4 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doResolveUris } from 'redux/actions/claims';
import { selectClaimForUri, selectMyClaimIdsRaw } from 'redux/selectors/claims'; import { selectClaimForUri, selectMyClaimIdsRaw } from 'redux/selectors/claims';
import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket'; import { doCommentSocketConnect, doCommentSocketDisconnect } from 'redux/actions/websocket';
import { doCommentList, doSuperChatList } from 'redux/actions/comments'; import { doCommentList, doSuperChatList } from 'redux/actions/comments';
@ -28,4 +29,5 @@ export default connect(select, {
doCommentSocketDisconnect, doCommentSocketDisconnect,
doCommentList, doCommentList,
doSuperChatList, doSuperChatList,
doResolveUris,
})(LivestreamComments); })(LivestreamComments);

View file

@ -27,11 +27,13 @@ type Props = {
doSuperChatList: (string) => void, doSuperChatList: (string) => void,
superChats: Array<Comment>, superChats: Array<Comment>,
myChannelIds: ?Array<string>, myChannelIds: ?Array<string>,
doResolveUris: (Array<string>, boolean) => void,
}; };
const VIEW_MODE_CHAT = 'view_chat'; const VIEW_MODE_CHAT = 'view_chat';
const VIEW_MODE_SUPER_CHAT = 'view_superchat'; const VIEW_MODE_SUPER_CHAT = 'view_superchat';
const COMMENT_SCROLL_TIMEOUT = 25; const COMMENT_SCROLL_TIMEOUT = 25;
const LARGE_SUPER_CHAT_LIST_THRESHOLD = 20;
export default function LivestreamComments(props: Props) { export default function LivestreamComments(props: Props) {
const { const {
@ -47,6 +49,7 @@ export default function LivestreamComments(props: Props) {
doSuperChatList, doSuperChatList,
myChannelIds, myChannelIds,
superChats: superChatsByTipAmount, superChats: superChatsByTipAmount,
doResolveUris,
} = props; } = props;
let superChatsFiatAmount, superChatsLBCAmount, superChatsTotalAmount, hasSuperChats; let superChatsFiatAmount, superChatsLBCAmount, superChatsTotalAmount, hasSuperChats;
@ -55,10 +58,10 @@ export default function LivestreamComments(props: Props) {
const [viewMode, setViewMode] = React.useState(VIEW_MODE_CHAT); const [viewMode, setViewMode] = React.useState(VIEW_MODE_CHAT);
const [scrollPos, setScrollPos] = React.useState(0); const [scrollPos, setScrollPos] = React.useState(0);
const [showPinned, setShowPinned] = React.useState(true); const [showPinned, setShowPinned] = React.useState(true);
const [resolvingSuperChat, setResolvingSuperChat] = React.useState(false);
const claimId = claim && claim.claim_id; const claimId = claim && claim.claim_id;
const commentsLength = commentsByChronologicalOrder && commentsByChronologicalOrder.length; const commentsLength = commentsByChronologicalOrder && commentsByChronologicalOrder.length;
// which kind of superchat to display, either
const commentsToDisplay = viewMode === VIEW_MODE_CHAT ? commentsByChronologicalOrder : superChatsByTipAmount; const commentsToDisplay = viewMode === VIEW_MODE_CHAT ? commentsByChronologicalOrder : superChatsByTipAmount;
const stickerSuperChats = const stickerSuperChats =
superChatsByTipAmount && superChatsByTipAmount.filter(({ comment }) => Boolean(parseSticker(comment))); superChatsByTipAmount && superChatsByTipAmount.filter(({ comment }) => Boolean(parseSticker(comment)));
@ -73,6 +76,26 @@ export default function LivestreamComments(props: Props) {
} }
}, [discussionElement]); }, [discussionElement]);
const superChatTopTen = React.useMemo(() => {
return superChatsByTipAmount ? superChatsByTipAmount.slice(0, 10) : superChatsByTipAmount;
}, [superChatsByTipAmount]);
const showMoreSuperChatsButton =
superChatTopTen && superChatsByTipAmount && superChatTopTen.length < superChatsByTipAmount.length;
function resolveSuperChat() {
if (superChatsByTipAmount && superChatsByTipAmount.length > 0) {
doResolveUris(
superChatsByTipAmount.map((comment) => comment.channel_url || '0'),
true
);
if (superChatsByTipAmount.length > LARGE_SUPER_CHAT_LIST_THRESHOLD) {
setResolvingSuperChat(true);
}
}
}
React.useEffect(() => { React.useEffect(() => {
if (claimId) { if (claimId) {
doCommentList(uri, '', 1, 75); doCommentList(uri, '', 1, 75);
@ -121,6 +144,24 @@ export default function LivestreamComments(props: Props) {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [commentsLength]); // (Just respond to 'commentsLength' updates and nothing else) }, [commentsLength]); // (Just respond to 'commentsLength' updates and nothing else)
// Stop spinner for resolving superchats
React.useEffect(() => {
if (resolvingSuperChat) {
// The real solution to the sluggishness is to fix the claim store/selectors
// and to paginate the long superchat list. This serves as a band-aid,
// showing a spinner while we batch-resolve. The duration is just a rough
// estimate -- the lag will handle the remaining time.
const timer = setTimeout(() => {
setResolvingSuperChat(false);
// Scroll to the top:
const livestreamCommentsDiv = document.getElementsByClassName('livestream__comments')[0];
const divHeight = livestreamCommentsDiv.scrollHeight;
livestreamCommentsDiv.scrollTop = divHeight * -1;
}, 1000);
return () => clearTimeout(timer);
}
}, [resolvingSuperChat]);
// sum total amounts for fiat tips and lbc tips // sum total amounts for fiat tips and lbc tips
if (superChatsByTipAmount) { if (superChatsByTipAmount) {
let fiatAmount = 0; let fiatAmount = 0;
@ -195,10 +236,8 @@ export default function LivestreamComments(props: Props) {
</> </>
} }
onClick={() => { onClick={() => {
resolveSuperChat();
setViewMode(VIEW_MODE_SUPER_CHAT); setViewMode(VIEW_MODE_SUPER_CHAT);
const livestreamCommentsDiv = document.getElementsByClassName('livestream__comments')[0];
const divHeight = livestreamCommentsDiv.scrollHeight;
livestreamCommentsDiv.scrollTop = divHeight * -1;
}} }}
/> />
</div> </div>
@ -214,7 +253,7 @@ export default function LivestreamComments(props: Props) {
{viewMode === VIEW_MODE_CHAT && superChatsByTipAmount && hasSuperChats && ( {viewMode === VIEW_MODE_CHAT && superChatsByTipAmount && hasSuperChats && (
<div className="livestream-superchats__wrapper"> <div className="livestream-superchats__wrapper">
<div className="livestream-superchats__inner"> <div className="livestream-superchats__inner">
{superChatsByTipAmount.map((superChat: Comment) => { {superChatTopTen.map((superChat: Comment) => {
const isSticker = stickerSuperChats && stickerSuperChats.includes(superChat); const isSticker = stickerSuperChats && stickerSuperChats.includes(superChat);
const SuperChatWrapper = !isSticker const SuperChatWrapper = !isSticker
@ -253,6 +292,18 @@ export default function LivestreamComments(props: Props) {
</SuperChatWrapper> </SuperChatWrapper>
); );
})} })}
{showMoreSuperChatsButton && (
<Button
title={__('Show More...')}
button="inverse"
className="close-button"
onClick={() => {
resolveSuperChat();
setViewMode(VIEW_MODE_SUPER_CHAT);
}}
icon={ICONS.MORE}
/>
)}
</div> </div>
</div> </div>
)} )}
@ -301,8 +352,14 @@ export default function LivestreamComments(props: Props) {
/> />
))} ))}
{/* listing comments on top of eachother */} {viewMode === VIEW_MODE_SUPER_CHAT && resolvingSuperChat && (
<div className="main--empty">
<Spinner />
</div>
)}
{viewMode === VIEW_MODE_SUPER_CHAT && {viewMode === VIEW_MODE_SUPER_CHAT &&
!resolvingSuperChat &&
superChatsReversed && superChatsReversed &&
superChatsReversed.map((comment) => ( superChatsReversed.map((comment) => (
<LivestreamComment <LivestreamComment

View file

@ -297,6 +297,11 @@ $recent-msg-button__height: 2rem;
.livestream-superchats__inner { .livestream-superchats__inner {
display: flex; display: flex;
.close-button {
padding-left: var(--spacing-m);
padding-right: var(--spacing-l);
}
} }
.livestream-superchat { .livestream-superchat {