{$content.confirm_leave_page}
+ }, + onConfirm, + onCancel + }); + } + }, [isBlocked, onCancel, onConfirm, openModal, isActive]); + + return ( ++ {question} +
+{`${$content.total_votes}: ${totalVotes.toLocaleString()}`}
++ {$content.winner} +
+ )} +{`${percentage}% (${countFormatted} ${voteContent})`}
+ )} +{$webBroadcastContent.go_live}
diff --git a/web-ui/src/tailwind.config.js b/web-ui/src/tailwind.config.js index 3c58878a..e7ba1b87 100644 --- a/web-ui/src/tailwind.config.js +++ b/web-ui/src/tailwind.config.js @@ -68,6 +68,13 @@ module.exports = { fontWeight: '500' } ], + p4: [ + '14px', + { + lineHeight: '17px', + fontWeight: 700 + } + ], h3: [ '1.125rem', { diff --git a/web-ui/src/tailwind/colors.js b/web-ui/src/tailwind/colors.js index 684c0a1d..b500ccd5 100644 --- a/web-ui/src/tailwind/colors.js +++ b/web-ui/src/tailwind/colors.js @@ -452,5 +452,56 @@ module.exports = { DEFAULT: 'hsl(var(--base-profile-color-lavender), 98%)' } } + }, + poll: { + green: { + pollVoteBg: 'hsl(var(--base-profile-color-green), 50%)', + pollButtonBg: 'hsl(var(--base-profile-color-green), 62%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-green), 22%)', + voteButtonHover: 'hsl(var(--base-profile-color-green), 71%)', + scrollBarThumb: 'hsl(var(--base-profile-color-green), 55%)' + }, + yellow: { + pollVoteBg: 'hsl(var(--base-profile-color-yellow), 75%)', + pollButtonBg: 'hsl(var(--base-profile-color-yellow), 85%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-yellow), 18%)', + voteButtonHover: 'hsl(var(--base-profile-color-yellow), 93%)', + scrollBarThumb: 'hsl(var(--base-profile-color-yellow), 80%)' + }, + blue: { + pollVoteBg: 'hsl(var(--base-profile-color-blue), 72%)', + pollButtonBg: 'hsl(var(--base-profile-color-blue), 80%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-blue), 24%)', + voteButtonHover: 'hsl(var(--base-profile-color-blue), 90%)', + scrollBarThumb: 'hsl(var(--base-profile-color-blue), 76%)' + }, + salmon: { + pollVoteBg: 'hsl(var(--base-profile-color-salmon), 81%)', + pollButtonBg: 'hsl(var(--base-profile-color-salmon), 90%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-salmon), 27%)', + voteButtonHover: 'hsl(var(--base-profile-color-salmon), 95%)', + scrollBarThumb: 'hsl(var(--base-profile-color-salmon), 85%)' + }, + purple: { + pollVoteBg: 'hsl(var(--base-profile-color-purple), 64%)', + pollButtonBg: 'hsl(var(--base-profile-color-purple), 78%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-purple), 29%)', + voteButtonHover: 'hsl(var(--base-profile-color-purple), 86%)', + scrollBarThumb: 'hsl(var(--base-profile-color-purple), 70%)' + }, + turquoise: { + pollVoteBg: 'hsl(var(--base-profile-color-turquoise), 87%)', + pollButtonBg: 'hsl(var(--base-profile-color-turquoise), 95%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-turquoise), 20%)', + voteButtonHover: 'hsl(var(--base-profile-color-turquoise), 99%)', + scrollBarThumb: 'hsl(var(--base-profile-color-turquoise), 90%)' + }, + lavender: { + pollVoteBg: 'hsl(var(--base-profile-color-lavender), 90%)', + pollButtonBg: 'hsl(var(--base-profile-color-lavender), 96%)', + pollWinnerTextColor: 'hsl(var(--base-profile-color-lavender), 36%)', + voteButtonHover: 'hsl(var(--base-profile-color-lavender), 99%)', + scrollBarThumb: 'hsl(var(--base-profile-color-lavender), 94%)' + } } }; diff --git a/web-ui/src/tailwind/safelist.js b/web-ui/src/tailwind/safelist.js index df70a246..f1f2a794 100644 --- a/web-ui/src/tailwind/safelist.js +++ b/web-ui/src/tailwind/safelist.js @@ -76,6 +76,24 @@ module.exports = [ pattern: /^bg-profile-([a-z]+)-darkMode-dark-hover$/, variants: ['dark:group-hover'] }, + { + pattern: /^bg-poll-([a-z]+)-pollVoteBg$/, + variants: ['dark:hover', 'hover', 'focus', 'dark:focus'] + }, + { + pattern: /^bg-poll-([a-z]+)-voteButtonHover$/, + variants: ['dark:hover', 'hover'] + }, + { + pattern: /^bg-poll-([a-z]+)-pollButtonBg$/, + variants: ['focus'] + }, + { + pattern: /^text-poll-([a-z]+)-pollWinnerTextColor$/ + }, + { + pattern: /^fill-poll-([a-z]+)-pollWinnerTextColor$/ + }, /** * Used in the useProfileViewPlayerAnimation hook */ @@ -85,5 +103,8 @@ module.exports = [ { pattern: /^overflow-y-overlay$/, variants: ['supports-overlay'] + }, + { + pattern: /^scrollbar-color-poll-([a-z]+)-scrollBarThumb$/ } ]; diff --git a/web-ui/src/utils.js b/web-ui/src/utils.js index 5e2f9541..154a2cbd 100644 --- a/web-ui/src/utils.js +++ b/web-ui/src/utils.js @@ -1,7 +1,11 @@ import { extendTailwindMerge, fromTheme } from 'tailwind-merge'; import clsx from 'clsx'; -import { CHANNEL_TYPE } from './constants'; +import { + BANNED_USERNAME_CHANNEL_ID_SEPARATOR, + CHANNEL_TYPE, + NUM_MILLISECONDS_TO_BLOCK +} from './constants'; export const noop = () => {}; @@ -194,7 +198,7 @@ const customTwMerge = extendTailwindMerge({ ] } ], - text: ['text-p1', 'text-p2', 'text-p3', 'text-h3'] + text: ['text-p1', 'text-p2', 'text-p3', 'text-p4', 'text-h3'] } }); @@ -297,12 +301,43 @@ export const convertConcurrentViews = (views) => { views /= 1000; index++; } - const hasDecimal = views % 1 !== 0; + + const formattedViews = Number( + Number.isInteger(views) ? views : views.toFixed(1) + ); return ( - (hasDecimal ? views.toFixed(index === 0 ? 0 : 1) : views) + + (formattedViews % 1 === 0 ? formattedViews.toFixed() : formattedViews) + abbreviations[index] ); }; export const isS3Url = (url = '') => url.includes('.s3.'); + +export const extractChannelIdfromChannelArn = (bannedUserChannelArn) => + bannedUserChannelArn + .split(BANNED_USERNAME_CHANNEL_ID_SEPARATOR)[1] + ?.toLowerCase(); + +export const updateVotes = (message, votes) => { + const selectedOption = message.attributes?.option; + + return votes.map((voteOption) => { + return voteOption.option === selectedOption + ? { ...voteOption, count: voteOption.count + 1 } + : voteOption; + }); +}; + +export const isVotingBlocked = (duration, startTime) => { + const now = Date.now(); + + return startTime + duration * 1000 - now <= NUM_MILLISECONDS_TO_BLOCK; +}; + +export const isElementsOverlapping = (element1, element2) => { + const el1 = element1?.getBoundingClientRect(); + const el2 = element2?.getBoundingClientRect(); + + return el1?.bottom > el2?.top && el1?.top < el2?.bottom; +};