diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e04b759af..594ca25578 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.13.2] - 2023-11-14 + +### Changed + +- YPP payout date is moved to Tuesday +- Account seed is now downloaded by default +- Changed referrals list on referrals page + +### Fixed + +- Fixed performance issues on mobile devices +- Fixed player styling on mobile devices +- Fixed incorrect rewards on YPP dashboard tab + ## [4.13.1] - 2023-11-09 ### Fixed diff --git a/packages/atlas/atlas.config.yml b/packages/atlas/atlas.config.yml index 045e3644db..4f1d39fd42 100644 --- a/packages/atlas/atlas.config.yml +++ b/packages/atlas/atlas.config.yml @@ -1,5 +1,5 @@ general: - appName: Atlas # Application name - used in the copy throughout the app, in index.html, open graph meta tags, etc. Don't use env variables here + appName: Gleev # Application name - used in the copy throughout the app, in index.html, open graph meta tags, etc. Don't use env variables here appDescription: 'The streaming platform empowering viewers, creators, and builders. Built on and operated by the Joystream blockchain and DAO.' # Application description - used in index.html meta tags appTagline: 'The streaming platform empowering viewers, creators, and builders. Built on and operated by the Joystream blockchain and DAO.' appId: '$VITE_APP_ID' # App ID for Apps as first-class citizens diff --git a/packages/atlas/package.json b/packages/atlas/package.json index e5c43bd095..70d59ae471 100644 --- a/packages/atlas/package.json +++ b/packages/atlas/package.json @@ -1,7 +1,7 @@ { "name": "@joystream/atlas", "description": "UI for consuming Joystream - a user governed video platform", - "version": "4.13.1", + "version": "4.13.2", "license": "GPL-3.0", "scripts": { "start": "vite", @@ -96,7 +96,7 @@ "retry-axios": "^3.0.0", "scroll-lock": "^2.1.5", "subscriptions-transport-ws": "^0.11.0", - "swiper": "^9.1.1", + "swiper": "11.0.4", "twemoji": "^14.0.2", "use-draggable-scroll": "^0.1.0", "use-resize-observer": "^9.1.0", diff --git a/packages/atlas/src/api/hooks/nfts.ts b/packages/atlas/src/api/hooks/nfts.ts index 922a68b5fc..ea41000436 100644 --- a/packages/atlas/src/api/hooks/nfts.ts +++ b/packages/atlas/src/api/hooks/nfts.ts @@ -194,9 +194,6 @@ export const useFeaturedNftsVideos = () => { variables: { limit: 10, orderBy: [OwnedNftOrderByInput.VideoViewsNumDesc], - where: { - isFeatured_eq: true, - }, }, }) diff --git a/packages/atlas/src/assets/images/referrals-landing/referrals-list.webp b/packages/atlas/src/assets/images/referrals-landing/referrals-list.webp index 00d436d754..ee34b92c89 100644 Binary files a/packages/atlas/src/assets/images/referrals-landing/referrals-list.webp and b/packages/atlas/src/assets/images/referrals-landing/referrals-list.webp differ diff --git a/packages/atlas/src/components/Avatar/Avatar.styles.ts b/packages/atlas/src/components/Avatar/Avatar.styles.ts index cc861916d1..90c4a81f6e 100644 --- a/packages/atlas/src/components/Avatar/Avatar.styles.ts +++ b/packages/atlas/src/components/Avatar/Avatar.styles.ts @@ -5,6 +5,7 @@ import styled from '@emotion/styled' import { SvgActionAddImage, SvgActionEdit, SvgIllustrativeFileFailed } from '@/assets/icons' import { SvgAvatarSilhouette } from '@/assets/illustrations' import { AssetImage } from '@/components/AssetImage' +import { smallBadgeStyles } from '@/components/Badge' import { SkeletonLoader } from '@/components/_loaders/SkeletonLoader' import { cVar, square, zIndex } from '@/styles' @@ -171,3 +172,15 @@ export const StyledSvgIllustrativeFileFailed = styled(SvgIllustrativeFileFailed) fill: ${cVar('colorCoreNeutral100')}; } ` + +export const BadgeContainer = styled.div<{ 'data-badge': string | number | boolean | undefined }>` + display: ${(props) => (props['data-badge'] ? 'block' : 'contents')}; + position: relative; + ${smallBadgeStyles} + + &[data-badge]::after { + position: absolute; + right: -6px; + top: -6px; + } +` diff --git a/packages/atlas/src/components/Carousel/Carousel.styles.ts b/packages/atlas/src/components/Carousel/Carousel.styles.ts index 4a6ffa1081..85fd6cb834 100644 --- a/packages/atlas/src/components/Carousel/Carousel.styles.ts +++ b/packages/atlas/src/components/Carousel/Carousel.styles.ts @@ -1,6 +1,6 @@ import styled from '@emotion/styled' -import { SwiperOptions } from 'swiper' import { Swiper } from 'swiper/react' +import { SwiperOptions } from 'swiper/types' import { Button } from '@/components/_buttons/Button' import { cVar, media, sizes, transitions, zIndex } from '@/styles' diff --git a/packages/atlas/src/components/Carousel/Carousel.tsx b/packages/atlas/src/components/Carousel/Carousel.tsx index c5fa72eff0..8066b74b8b 100644 --- a/packages/atlas/src/components/Carousel/Carousel.tsx +++ b/packages/atlas/src/components/Carousel/Carousel.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react' -import { Pagination } from 'swiper' import 'swiper/css' +import { Navigation, Pagination } from 'swiper/modules' import { SwiperProps, SwiperSlide } from 'swiper/react' import { Swiper as SwiperType } from 'swiper/types' @@ -15,7 +15,7 @@ export type CarouselProps = { } & SwiperProps const dotsProps = { - modules: [Pagination], + modules: [Pagination, Navigation], pagination: { clickable: true, bulletClass: 'bullet', diff --git a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/MarketplaceCarouselCard.styles.ts b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/MarketplaceCarouselCard.styles.ts index 8a797ad3df..bc44ee94b3 100644 --- a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/MarketplaceCarouselCard.styles.ts +++ b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/MarketplaceCarouselCard.styles.ts @@ -20,7 +20,7 @@ export const InformationContainer = styled.div<{ isPaused: boolean }>` } ` -export const Container = styled.div<{ isActive: boolean }>` +export const Container = styled.div` display: flex; flex-direction: column; position: relative; diff --git a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx index 38ecfc0c06..927d16d322 100644 --- a/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx +++ b/packages/atlas/src/components/NftCarousel/components/MarketplaceCarouselCard/NftCarouselDetails.tsx @@ -20,8 +20,10 @@ import { Text } from '@/components/Text' import { SkeletonLoader } from '@/components/_loaders/SkeletonLoader' import { DetailsContent } from '@/components/_nft/NftTile' import { BackgroundVideoPlayer } from '@/components/_video/BackgroundVideoPlayer' +import { VideoPoster, VideoWrapper } from '@/components/_video/BackgroundVideoPlayer/BackgroundVideoPlayer.styles' import { absoluteRoutes } from '@/config/routes' import { useBlockTimeEstimation } from '@/hooks/useBlockTimeEstimation' +import { useDebounceValue } from '@/hooks/useDebounceValue' import { useMediaMatch } from '@/hooks/useMediaMatch' import { hapiBnToTokenNumber } from '@/joystream-lib/utils' import { getMemberAvatar } from '@/providers/assets/assets.helpers' @@ -42,6 +44,7 @@ export const NftCarouselDetails = ({ const [isPaused, setIsPaused] = useState(!active) const { convertBlockToMsTimestamp } = useBlockTimeEstimation() const nftStatus = getNftStatus(nft, nft?.video) + const debouncedActive = useDebounceValue(active, 500) const ownerAvatarUrls = nft.owner.__typename === 'NftOwnerChannel' @@ -157,97 +160,101 @@ export const NftCarouselDetails = ({ } return ( - + - setIsPaused(true)} - onPlay={() => setIsPaused(false)} - preload="auto" - src={mediaUrls ?? undefined} - poster={thumbnailUrls ?? undefined} - handleActions={active} - videoPlaytime={30} - onEnded={slideNext} - /> + {!active ? ( + + + + ) : ( + setIsPaused(true)} + onPlay={() => setIsPaused(false)} + preload="auto" + src={mediaUrls ?? undefined} + poster={thumbnailUrls ?? undefined} + handleActions={active ? debouncedActive : active} + videoPlaytime={30} + onEnded={slideNext} + /> + )} - {active && ( - - - - - - {nftDetails.title} - - - {nftDetails.buyNow && ( - } - withDenomination - /> - )} - {nftDetails.topBid && ( - } - withDenomination - /> - )} - {nftDetails.minBid && ( - } - withDenomination - /> - )} - {nftStatus?.status === 'idle' && ( - } - /> - )} + + + + + + {nftDetails.title} + + + {nftDetails.buyNow && ( + } + withDenomination + /> + )} + {nftDetails.topBid && ( + } + withDenomination + /> + )} + {nftDetails.minBid && ( + } + withDenomination + /> + )} + {nftStatus?.status === 'idle' && ( + } + /> + )} - {timeLeft && ( - { - return ( - <> - {i !== 0 ? ( - - : - - ) : null} - - {tick} + {timeLeft && ( + { + return ( + <> + {i !== 0 ? ( + + : - - ) - })} - /> - )} - - - - - )} + ) : null} + + {tick} + + + ) + })} + /> + )} + + + + ) } diff --git a/packages/atlas/src/components/_auth/SignUpModal/SignUpModal.tsx b/packages/atlas/src/components/_auth/SignUpModal/SignUpModal.tsx index cb6c62dc99..28b04396f0 100644 --- a/packages/atlas/src/components/_auth/SignUpModal/SignUpModal.tsx +++ b/packages/atlas/src/components/_auth/SignUpModal/SignUpModal.tsx @@ -38,7 +38,7 @@ const SIGNUP_FORM_DATA_INITIAL_STATE: AccountFormData & MemberFormData = { avatar: undefined, captchaToken: undefined, confirmedTerms: false, - confirmedCopy: false, + allowDownload: true, memberId: '', referrerChannelId: undefined, } @@ -248,7 +248,7 @@ export const SignUpModal = () => { ) const handleCreateMemberOnSeedStepSubmit = useCallback( - async (mnemonic: string, confirmedCopy: boolean) => { + async (mnemonic: string, allowDownload: boolean) => { let handle = signUpFormData.current.handle let blob = signUpFormData.current.avatar?.blob @@ -266,8 +266,8 @@ export const SignUpModal = () => { const memberData = { mnemonic, + allowDownload, handle, - confirmedCopy, avatar: blob ? { blob } : undefined, } @@ -383,7 +383,7 @@ export const SignUpModal = () => { {...commonProps} onSeedSubmit={handleCreateMemberOnSeedStepSubmit} mnemonic={signUpFormData.current.mnemonic} - confirmedCopy={signUpFormData.current.confirmedCopy} + allowDownload={signUpFormData.current.allowDownload} /> )} {currentStep === SignUpSteps.SignUpPassword && ( diff --git a/packages/atlas/src/components/_auth/SignUpModal/SignUpSteps/SignUpSeedStep/SignUpSeedStep.tsx b/packages/atlas/src/components/_auth/SignUpModal/SignUpSteps/SignUpSeedStep/SignUpSeedStep.tsx index 98b23ffcea..1c79135487 100644 --- a/packages/atlas/src/components/_auth/SignUpModal/SignUpSteps/SignUpSeedStep/SignUpSeedStep.tsx +++ b/packages/atlas/src/components/_auth/SignUpModal/SignUpSteps/SignUpSeedStep/SignUpSeedStep.tsx @@ -2,21 +2,20 @@ import { mnemonicGenerate } from '@polkadot/util-crypto' import { FC, useCallback, useEffect, useRef } from 'react' import { Controller, useForm } from 'react-hook-form' -import { SvgActionCopy } from '@/assets/icons' import { AuthenticationModalStepTemplate } from '@/components/_auth/AuthenticationModalStepTemplate' import { Checkbox } from '@/components/_inputs/Checkbox' import { FormField } from '@/components/_inputs/FormField' import { MemberFormData } from '@/hooks/useCreateMember' -import { StyledTextArea, StyledTextButton } from './SignupSeedStep.styles' +import { StyledTextArea } from './SignupSeedStep.styles' -import { CheckboxWrapper, StyledSignUpForm } from '../SignUpSteps.styles' +import { StyledSignUpForm } from '../SignUpSteps.styles' import { SignUpStepsCommonProps } from '../SignUpSteps.types' -type FormData = Pick +type FormData = Pick type SignUpSeedStepProps = { - onSeedSubmit: (mnemonic: string, confirmedCopy: boolean) => void + onSeedSubmit: (mnemonic: string, allowDownload: boolean) => void } & SignUpStepsCommonProps & FormData @@ -24,20 +23,12 @@ export const SignUpSeedStep: FC = ({ hasNavigatedBack, setPrimaryButtonProps, mnemonic, - confirmedCopy, onSeedSubmit, }) => { - const { - control, - register, - getValues, - handleSubmit, - setValue, - formState: { errors }, - } = useForm({ + const { control, register, getValues, handleSubmit, setValue } = useForm({ shouldFocusError: true, defaultValues: { - confirmedCopy: confirmedCopy, + allowDownload: true, mnemonic, }, }) @@ -51,22 +42,25 @@ export const SignUpSeedStep: FC = ({ }, [mnemonic, setValue]) const handleGoToNextStep = useCallback(() => { - handleSubmit((data) => { - onSeedSubmit(data.mnemonic, data.confirmedCopy) - })() - }, [handleSubmit, onSeedSubmit]) + const downloadSeed = () => { + const blobText = new Blob([getValues('mnemonic')], { type: 'text/plain' }) + const url = URL.createObjectURL(blobText) + const link = document.createElement('a') + link.href = url + link.download = 'mnemonic.txt' + link.click() - const downloadSeed = () => { - const blobText = new Blob([getValues('mnemonic')], { type: 'text/plain' }) - const url = URL.createObjectURL(blobText) - const link = document.createElement('a') - link.href = url - link.download = 'mnemonic.txt' - link.click() + link.remove() + URL.revokeObjectURL(url) + } - link.remove() - URL.revokeObjectURL(url) - } + handleSubmit((data) => { + onSeedSubmit(data.mnemonic, data.allowDownload) + if (data.allowDownload) { + downloadSeed() + } + })() + }, [getValues, handleSubmit, onSeedSubmit]) useEffect(() => { setPrimaryButtonProps({ @@ -77,7 +71,6 @@ export const SignUpSeedStep: FC = ({ return ( = ({ - } iconPlacement="left" onClick={downloadSeed}> - Download as text file - { - if (!value) { - return 'Agree that you saved your wallet seed phrase safely.' - } else { - return value - } - }, - }, - }} + name="allowDownload" render={({ field: { onChange, value } }) => ( - - onChange(val)} - caption={errors.confirmedCopy?.message} - error={!!errors.confirmedCopy} - value={value} - label="I have saved my wallet seed phrase safely" - /> - + onChange(val)} + value={value} + label="Download the wallet seed as .txt file" + caption="Download will start after clicking continue" + /> )} /> diff --git a/packages/atlas/src/hooks/useCreateMember.ts b/packages/atlas/src/hooks/useCreateMember.ts index dcea8aa1d2..e3bb8c6525 100644 --- a/packages/atlas/src/hooks/useCreateMember.ts +++ b/packages/atlas/src/hooks/useCreateMember.ts @@ -28,7 +28,7 @@ export type MemberFormData = { mnemonic: string authorizationCode?: string userId?: string - confirmedCopy: boolean + allowDownload: boolean referrerChannelId?: string } diff --git a/packages/atlas/src/utils/time.ts b/packages/atlas/src/utils/time.ts index 3e70137327..82856f8332 100644 --- a/packages/atlas/src/utils/time.ts +++ b/packages/atlas/src/utils/time.ts @@ -71,10 +71,11 @@ export const convertDateFormat = (timestamp: Date | string) => { return timestamp instanceof Date ? timestamp : parseISO(timestamp) } -export const getNextFriday = (date = new Date()) => { +// weekday: 1 - monday, 2 - tuesday ... 7- sunday +export const getNextWeekday = (date = new Date(), weekday = 1) => { const nextDate = new Date(date) const currentDayOfWeek = nextDate.getDay() - const daysToAdd = currentDayOfWeek <= 5 ? 5 - currentDayOfWeek : 7 - currentDayOfWeek + 5 + const daysToAdd = currentDayOfWeek <= weekday ? weekday - currentDayOfWeek : 7 - currentDayOfWeek + weekday nextDate.setDate(nextDate.getDate() + daysToAdd) return nextDate } diff --git a/packages/atlas/src/utils/ypp.ts b/packages/atlas/src/utils/ypp.ts index 69281e33e4..d7b8f83383 100644 --- a/packages/atlas/src/utils/ypp.ts +++ b/packages/atlas/src/utils/ypp.ts @@ -4,7 +4,7 @@ import { YppChannelStatus } from '@/views/global/YppLandingView/YppLandingView.t const configTiers = atlasConfig.features.ypp.tiersDefinition type ConfigTier = typeof configTiers[number]['tier'] -export const yppBackendTierToConfig = (beTier: YppChannelStatus): ConfigTier | undefined => { +export const yppBackendTierToConfig = (beTier?: YppChannelStatus): ConfigTier | undefined => { switch (beTier) { case 'Verified::Bronze': return 'bronze' diff --git a/packages/atlas/src/views/studio/YppDashboard/tabs/YppDashboardMainTab.tsx b/packages/atlas/src/views/studio/YppDashboard/tabs/YppDashboardMainTab.tsx index a935ba4409..a9bd80e955 100644 --- a/packages/atlas/src/views/studio/YppDashboard/tabs/YppDashboardMainTab.tsx +++ b/packages/atlas/src/views/studio/YppDashboard/tabs/YppDashboardMainTab.tsx @@ -20,7 +20,7 @@ import { useMediaMatch } from '@/hooks/useMediaMatch' import { useYppAuthorizeHandler } from '@/hooks/useYppAuthorizeHandler' import { usePersonalDataStore } from '@/providers/personalData' import { useUser } from '@/providers/user/user.hooks' -import { formatDate, getNextFriday } from '@/utils/time' +import { formatDate, getNextWeekday } from '@/utils/time' import { BOOST_TIMESTAMP, getTierRewards, yppBackendTierToConfig } from '@/utils/ypp' import { YppAuthorizationModal } from '@/views/global/YppLandingView/YppAuthorizationModal' import { configYppIconMapper } from '@/views/global/YppLandingView/sections/YppFooter' @@ -53,8 +53,9 @@ export const YppDashboardMainTab: FC = () => { const mdMatch = useMediaMatch('md') const smMatch = useMediaMatch('sm') const lgMatch = useMediaMatch('lg') - const nextPayoutDate = getNextFriday() + const nextPayoutDate = getNextWeekday(new Date(), 2) const rewardMultiplier = + yppBackendTierToConfig(currentChannel?.yppStatus) !== 'bronze' && new Date(currentChannel?.createdAt || 0).getTime() > BOOST_TIMESTAMP ? atlasConfig.features.ypp.tierBoostMultiplier || 1 : 1 @@ -109,7 +110,7 @@ export const YppDashboardMainTab: FC = () => { { } description={ currentChannel?.yppStatus.startsWith('Verified') - ? `You will receive sign up bonus on (Friday) ${formatDate(nextPayoutDate)}` + ? `You will receive sign up bonus on (Tuesday) ${formatDate(nextPayoutDate)}` : 'Connect you YouTube channels via a step-by-step flow and get your first reward. You can sign up with multiple channels!' } dollarAmount={ diff --git a/packages/atlas/src/views/viewer/VideoView/VideoView.styles.ts b/packages/atlas/src/views/viewer/VideoView/VideoView.styles.ts index 7b9b2aa04f..ee8fb5548e 100644 --- a/packages/atlas/src/views/viewer/VideoView/VideoView.styles.ts +++ b/packages/atlas/src/views/viewer/VideoView/VideoView.styles.ts @@ -48,6 +48,7 @@ const getPlayerWrapperCinematicStyles = ({ cinematicView }: CinematicView) => ` export const PlayerWrapper = styled(LayoutGrid)` + width: inherit; ${getPlayerWrapperCinematicStyles}; ` diff --git a/yarn.lock b/yarn.lock index 7028a35a6a..f5994a5b8e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4350,7 +4350,7 @@ __metadata: storybook: 7.0.7 style-dictionary: ^3.7.1 subscriptions-transport-ws: ^0.11.0 - swiper: ^9.1.1 + swiper: 11.0.4 twemoji: ^14.0.2 use-draggable-scroll: ^0.1.0 use-resize-observer: ^9.1.0 @@ -20743,13 +20743,6 @@ __metadata: languageName: node linkType: hard -"ssr-window@npm:^4.0.2": - version: 4.0.2 - resolution: "ssr-window@npm:4.0.2" - checksum: df182600927f4f3225224cf8c02338ea637c9750519505bbfb9a9236741a2a7ec088386fb948bca7b447b8303d9109e7dc7672e3de041c79ac2a0e03665af7d2 - languageName: node - linkType: hard - "ssri@npm:^9.0.0": version: 9.0.1 resolution: "ssri@npm:9.0.1" @@ -21229,12 +21222,10 @@ __metadata: languageName: node linkType: hard -"swiper@npm:^9.1.1": - version: 9.1.1 - resolution: "swiper@npm:9.1.1" - dependencies: - ssr-window: ^4.0.2 - checksum: 053d606f03eb4f59be95dd3a6129b6fde559b5c1f042ab0c1240df12e0cbac32e2ab81a7334ca9781309bf34edd18ebe308d31b1064fdfba98120f0b20e48b93 +"swiper@npm:11.0.4": + version: 11.0.4 + resolution: "swiper@npm:11.0.4" + checksum: 520a4c0c1aeb94eadc5c2cf52ae4a479a2c7fc416ed15a7623135c4f1b0dc9ad255c2d0c1ec8e7a138e685ac37e95668aebfbd5a8d86887326a08e8b683bed51 languageName: node linkType: hard