diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml index d07653140..9a6f121ca 100644 --- a/.github/workflows/build-deploy.yml +++ b/.github/workflows/build-deploy.yml @@ -72,11 +72,16 @@ jobs: GH_GA_ID=G-TP1XEFNHQD GH_APP_KIND=polkaverse GH_HCAPTCHA_SITE_KEY=${{ secrets.PROD_HCAPTCHA_SITE_KEY }} - GH_AMP_ID=71bf5a46800fedba5e9a01243b988164 + GH_AMP_ID=2eeca0e8a0163c89e3f023c971e426a6 GH_OFFCHAIN_SIGNER_URL=https://signer.subsocial.network GH_CONNECTION_KIND=main GH_SELLER_CLIENT_ID=${{ secrets.SELLER_CLIENT_ID }} GH_SELLER_TOKEN_SIGNER=${{ secrets.SELLER_TOKEN_SIGNER }} + GH_SERVER_MNEMONIC=${{ secrets.SERVER_MNEMONIC }} + GH_NEXT_PUBLIC_DATAHUB_QUERY_URL=https://sub-data-hub.subsocial.network/graphql + GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL=wss://sub-data-hub.subsocial.network/graphql-ws + GH_DATAHUB_QUEUE_URL=https://sub-queue-data-hub.subsocial.network/graphql + GH_DATAHUB_QUEUE_TOKEN=${{ secrets.DATAHUB_QUEUE_TOKEN }} tags: | ${{ env.image }} diff --git a/.github/workflows/feature-based.yaml b/.github/workflows/feature-based.yaml index 3f517bb61..3d17c45cb 100644 --- a/.github/workflows/feature-based.yaml +++ b/.github/workflows/feature-based.yaml @@ -67,6 +67,11 @@ jobs: GH_CONNECTION_KIND=dev GH_SELLER_CLIENT_ID=5DYm3Wk4aa1BbfhH1ajmY6MNEELXoicmKRnP4tzHYjSKnD9K GH_SELLER_TOKEN_SIGNER=retire strong pole intact cool music high path salt praise stadium spatial + GH_SERVER_MNEMONIC=plunge pumpkin penalty segment cattle more print below fat lemon clap uniform + GH_NEXT_PUBLIC_DATAHUB_QUERY_URL=https://super-likes-fixed-data-hub.subsocial.network/graphql + GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL=wss://super-likes-fixed-data-hub.subsocial.network/graphql-ws + GH_DATAHUB_QUEUE_URL=https://super-likes-fixed-queue-data-hub.subsocial.network/graphql + GH_DATAHUB_QUEUE_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6dHJ1ZX0.jpXwkIJ4DpV4IvSI3eWVVXE6x89qr_GIq7IlbBv5YE0 tags: | ${{ env.image }} cache-from: type=local,src=/tmp/.buildx-cache diff --git a/ci.env b/ci.env index 63260b409..841d8fbc5 100644 --- a/ci.env +++ b/ci.env @@ -9,3 +9,8 @@ NEXT_PUBLIC_OFFCHAIN_SIGNER_URL='$GH_OFFCHAIN_SIGNER_URL' NEXT_PUBLIC_AMP_ID='$GH_AMP_ID' SELLER_CLIENT_ID='$GH_SELLER_CLIENT_ID' SELLER_CLIENT_TOKEN_SIGNER='$GH_SELLER_TOKEN_SIGNER' +NEXT_PUBLIC_DATAHUB_QUERY_URL='GH_NEXT_PUBLIC_DATAHUB_QUERY_URL' +NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL='GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL' +DATAHUB_QUEUE_URL='GH_DATAHUB_QUEUE_URL' +DATAHUB_QUEUE_TOKEN='GH_DATAHUB_QUEUE_TOKEN' +SERVER_MNEMONIC='GH_SERVER_MNEMONIC' diff --git a/cypress.config.ts b/cypress.config.ts deleted file mode 100644 index 6ea6b2fa2..000000000 --- a/cypress.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineConfig } from 'cypress' - -export default defineConfig({ - e2e: { - baseUrl: 'http://localhost:3003', - env: { - my_address: '3shk6xYyNwwL5yvDVCUoUVoa8iUu3QmsR64kVqi2jL25kyzf', - my_space: '5496', - my_post: '36193', - - fresh_account: '5HbAUnWjfS6xix33S5RMi1R99oG2TDMraQSRY4bP3fvycbSa', - account_with_energy: '5FHYXx3iHURLfdNk5svSQMuZA7nvzsk5CfwFtQMtivYWcYjG', - }, - }, -}) diff --git a/docker/Dockerfile b/docker/Dockerfile index d3bfe17ab..14e12b09e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,6 +9,11 @@ ARG GH_AMP_ID ARG GH_OFFCHAIN_SIGNER_URL ARG GH_SELLER_CLIENT_ID ARG GH_SELLER_TOKEN_SIGNER +ARG GH_NEXT_PUBLIC_DATAHUB_QUERY_URL +ARG GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL +ARG GH_DATAHUB_QUEUE_URL +ARG GH_DATAHUB_QUEUE_TOKEN +ARG GH_SERVER_MNEMONIC ENV NEXT_PUBLIC_GA_ID=${GH_GA_ID} \ NEXT_PUBLIC_APP_KIND=${GH_APP_KIND} \ @@ -18,7 +23,12 @@ ENV NEXT_PUBLIC_GA_ID=${GH_GA_ID} \ NEXT_PUBLIC_OFFCHAIN_SIGNER_URL=${GH_OFFCHAIN_SIGNER_URL} \ NEXT_PUBLIC_CONNECTION_KIND=${GH_CONNECTION_KIND} \ SELLER_CLIENT_ID=${GH_SELLER_CLIENT_ID} \ - SELLER_CLIENT_TOKEN_SIGNER=${GH_SELLER_TOKEN_SIGNER} + SELLER_CLIENT_TOKEN_SIGNER=${GH_SELLER_TOKEN_SIGNER} \ + NEXT_PUBLIC_DATAHUB_QUERY_URL=${GH_NEXT_PUBLIC_DATAHUB_QUERY_URL} \ + NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL=${GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL} \ + DATAHUB_QUEUE_URL=${GH_DATAHUB_QUEUE_URL} \ + DATAHUB_QUEUE_TOKEN=${GH_DATAHUB_QUEUE_TOKEN} \ + SERVER_MNEMONIC=${GH_SERVER_MNEMONIC} COPY package.json yarn.lock* ./ RUN yarn install --no-optional @@ -42,6 +52,11 @@ ARG GH_AMP_ID ARG GH_OFFCHAIN_SIGNER_URL ARG GH_SELLER_CLIENT_ID ARG GH_SELLER_TOKEN_SIGNER +ARG GH_NEXT_PUBLIC_DATAHUB_QUERY_URL +ARG GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL +ARG GH_DATAHUB_QUEUE_URL +ARG GH_DATAHUB_QUEUE_TOKEN +ARG GH_SERVER_MNEMONIC ENV NEXT_PUBLIC_GA_ID=${GH_GA_ID} \ NEXT_PUBLIC_APP_KIND=${GH_APP_KIND} \ @@ -50,7 +65,12 @@ ENV NEXT_PUBLIC_GA_ID=${GH_GA_ID} \ NEXT_PUBLIC_OFFCHAIN_SIGNER_URL=${GH_OFFCHAIN_SIGNER_URL} \ NEXT_PUBLIC_CONNECTION_KIND=${GH_CONNECTION_KIND} \ SELLER_CLIENT_ID=${GH_SELLER_CLIENT_ID} \ - SELLER_CLIENT_TOKEN_SIGNER=${GH_SELLER_TOKEN_SIGNER} + SELLER_CLIENT_TOKEN_SIGNER=${GH_SELLER_TOKEN_SIGNER} \ + NEXT_PUBLIC_DATAHUB_QUERY_URL=${GH_NEXT_PUBLIC_DATAHUB_QUERY_URL} \ + NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL=${GH_NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL} \ + DATAHUB_QUEUE_URL=${GH_DATAHUB_QUEUE_URL} \ + DATAHUB_QUEUE_TOKEN=${GH_DATAHUB_QUEUE_TOKEN} \ + SERVER_MNEMONIC=${GH_SERVER_MNEMONIC} WORKDIR /opt/subsocial/app diff --git a/package.json b/package.json index 894985bf6..b16a6f4d4 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "@typescript-eslint/parser": "^5.45.0", "@welldone-software/why-did-you-render": "^6.2.1", "apollo": "^2.34.0", - "cypress": "^10.11.0", "cypress-network-idle": "^1.10.2", "cypress-wait-until": "^1.7.2", "eslint": "^8.46.0", @@ -90,6 +89,7 @@ "@polkadot/ui-keyring": "^2.9.8", "@reduxjs/toolkit": "^1.3.4", "@subsocial/api": "0.8.10", + "@subsocial/data-hub-sdk": "dappforce/subsocial-data-hub-sdk#staging", "@subsocial/definitions": "0.8.10", "@subsocial/elasticsearch": "0.8.10", "@subsocial/grill-widget": "^0.0.13", @@ -122,7 +122,9 @@ "graphql": "^15.5.0", "graphql-request": "^5.2.0", "graphql-tag": "^2.11.0", + "graphql-ws": "^5.14.3", "isbot": "^3.0.14", + "isomorphic-ws": "^5.0.0", "jdenticon": "^3.2.0", "jwt-decode": "^3.1.2", "localforage": "^1.7.4", @@ -146,7 +148,7 @@ "react-embed": "^3.6.0", "react-ga": "^3.3.0", "react-hook-form": "~5.6.0", - "react-icons": "^4.4.0", + "react-icons": "^4.12.0", "react-infinite-scroll-component": "^6.1.0", "react-lite-youtube-embed": "^2.4.0", "react-markdown": "6.0.3", @@ -160,6 +162,7 @@ "store": "^2.0.12", "strip-markdown": "^4.0.0", "url-loader": "^4.1.1", - "yup": "^0.32.9" + "yup": "^0.32.9", + "zod": "^3.22.4" } } diff --git a/public/images/creators/subsocial-tokens-large.png b/public/images/creators/subsocial-tokens-large.png new file mode 100644 index 000000000..d8ecb7dc0 Binary files /dev/null and b/public/images/creators/subsocial-tokens-large.png differ diff --git a/public/images/databases.svg b/public/images/databases.svg index 7ecbe5bfb..f4544d2ff 100644 --- a/public/images/databases.svg +++ b/public/images/databases.svg @@ -1,6 +1,6 @@ - - + + diff --git a/public/images/diamond.svg b/public/images/diamond.svg new file mode 100644 index 000000000..7d993ae4e --- /dev/null +++ b/public/images/diamond.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/wallets/nova-wallet.jpeg b/public/images/wallets/nova-wallet.jpeg new file mode 100644 index 000000000..5252061e7 Binary files /dev/null and b/public/images/wallets/nova-wallet.jpeg differ diff --git a/src/components/auth/MyAccountsContext.tsx b/src/components/auth/MyAccountsContext.tsx index fdf155c4d..5f3e8170c 100644 --- a/src/components/auth/MyAccountsContext.tsx +++ b/src/components/auth/MyAccountsContext.tsx @@ -24,6 +24,7 @@ import { signOut, unsetMyEmailAddress, } from 'src/rtk/features/accounts/myAccountSlice' +import { fetchAddressLikeCounts } from 'src/rtk/features/activeStaking/addressLikeCountSlice' import { fetchChainsInfo } from 'src/rtk/features/chainsInfo/chainsInfoSlice' import { fetchProfileSpace } from 'src/rtk/features/profiles/profilesSlice' import { fetchEntityOfSpaceIdsByFollower } from 'src/rtk/features/spaceIds/followedSpaceIdsSlice' @@ -148,6 +149,7 @@ export function MyAccountsProvider(props: React.PropsWithChildren<{}>) { dispatch(fetchProfileSpace({ id: address, api: subsocial })), dispatch(fetchEntityOfSpaceIdsByFollower({ id: address, reload: true, api: subsocial })), dispatch(fetchChainsInfo({})), + dispatch(fetchAddressLikeCounts({ address, postIds: null })), ]) unsubAccountInfo = await readyApi.query.system.account( diff --git a/src/components/auth/WalletButton.tsx b/src/components/auth/WalletButton.tsx index 78e6f3a80..e02406c72 100644 --- a/src/components/auth/WalletButton.tsx +++ b/src/components/auth/WalletButton.tsx @@ -1,4 +1,6 @@ -import { AvatarOrSkeleton } from '../utils' +import Link from 'next/link' +import { hasInjectedWallet } from 'src/utils/window' +import { AvatarOrSkeleton, isClientSide } from '../utils' import { StepsEnum } from './AuthContext' import styles from './WalletButton.module.sass' @@ -11,6 +13,27 @@ const WalletButton = ({ setCurrentStep }: Props) => { setCurrentStep(StepsEnum.SelectAccount) } + const isInMobileWalletBrowser = isClientSide() && hasInjectedWallet() + if (!isInMobileWalletBrowser) { + return ( + + +
+ +
+ Install Nova Wallet +
+
+
+ + ) + } + return (
handleClick()}>
diff --git a/src/components/auth/signIn/SignInModal.tsx b/src/components/auth/signIn/SignInModal.tsx index 63cef4004..a6706cb3e 100644 --- a/src/components/auth/signIn/SignInModal.tsx +++ b/src/components/auth/signIn/SignInModal.tsx @@ -1,15 +1,14 @@ -import React, { useState } from 'react' -import LoadingTransaction from 'src/components/utils/LoadingTransaction' -import WalletButton from '../WalletButton' - import { ArrowLeftOutlined } from '@ant-design/icons' import { Button } from 'antd' import Modal from 'antd/lib/modal' import clsx from 'clsx' -import { useResponsiveSize } from 'src/components/responsive' +import React, { useState } from 'react' +import { useIsMobileWidthOrDevice, useResponsiveSize } from 'src/components/responsive' +import LoadingTransaction from 'src/components/utils/LoadingTransaction' import { setCurrentEmailAddress } from 'src/components/utils/OffchainSigner/ExternalStorage' import config from 'src/config' import { EmailAccount } from 'src/types' +import { hasInjectedWallet } from 'src/utils/window' import { AccountSelector } from '../../profile-selector/AccountSelector' import ExternalLink from '../../spaces/helpers/ExternalLink' import { MutedDiv } from '../../utils/MutedText' @@ -17,6 +16,7 @@ import PrivacyPolicyLinks from '../../utils/PrivacyPolicyLinks' import WalletList from '../../wallets/wallet-list/WalletsList' import { CompletedSteps, StepsEnum, useAuth } from '../AuthContext' import { useMyAccountsContext } from '../MyAccountsContext' +import WalletButton from '../WalletButton' import ConfirmationModalContent from './email/ConfirmationModalContent' import ShowMnemonicModalContent from './email/ShowMnemonicModalContent' import SignInEmailButton from './email/SignInEmailButton' @@ -190,19 +190,7 @@ const ModalContent = ({ case StepsEnum.SelectWallet: { return (
- - Choose one of the available wallet providers to connect to {config.appName}, or sign - in with your email address.{' '} - - - } - > + }> {config.enableConfirmationLessMode ? ( <> @@ -314,6 +302,27 @@ const ModalContent = ({ } } +function SignInDesc() { + const isMobile = useIsMobileWidthOrDevice() + if (isMobile) { + if (hasInjectedWallet()) { + return <>To use Polkaverse, you need to connect your wallet + } + return ( + <>To use PolkaVerse, you need a wallet to manage your account. We recommend Nova Wallet. + ) + } + return ( + <> + Choose one of the available wallet providers to connect to {config.appName}.{' '} + + + ) +} + export const SignInModalView = ({ open, hide, onAccountChosen }: SignInModalProps) => { const { state: { completedSteps, currentStep }, diff --git a/src/components/common/balances/Balance.tsx b/src/components/common/balances/Balance.tsx index e644d092d..d3839736b 100644 --- a/src/components/common/balances/Balance.tsx +++ b/src/components/common/balances/Balance.tsx @@ -25,10 +25,15 @@ function format( decimals: number, withSi?: boolean, _isShort?: boolean, + precision?: number, + withMutedDecimals = true, ): React.ReactNode { - const [prefix, postfix] = formatBalance(value, { forceUnit: '-', decimals, withSi: false }).split( - '.', - ) + const [prefix, postfix] = formatBalance(value, { + forceUnit: '-', + decimals, + withSi: false, + withZero: true, + }).split('.') const isShort = _isShort || (withSi && prefix.length >= K_LENGTH) if (prefix.length > M_LENGTH) { @@ -45,7 +50,12 @@ function format( {prefix} {!isShort && ( <> - .{postfix || '0000'} + . + + {precision + ? parseFloat(`0.${postfix}`).toPrecision(precision).substring(2) + : postfix || '0000'} + )}  {currency} @@ -58,6 +68,8 @@ type FormatBalanceProps = BareProps & { decimals?: number currency?: string isShort?: boolean + precision?: number + withMutedDecimals?: boolean } export const FormatBalance = ({ @@ -66,6 +78,8 @@ export const FormatBalance = ({ currency, isShort, className, + precision, + withMutedDecimals = true, ...bareProps }: FormatBalanceProps) => { if (!value) return null @@ -78,6 +92,8 @@ export const FormatBalance = ({ decimals || defaultDecimal, true, isShort, + precision, + withMutedDecimals, ) return ( diff --git a/src/components/creators/CreatorDashboardSidebar.tsx b/src/components/creators/CreatorDashboardSidebar.tsx index 556208544..6ae957baa 100644 --- a/src/components/creators/CreatorDashboardSidebar.tsx +++ b/src/components/creators/CreatorDashboardSidebar.tsx @@ -3,13 +3,15 @@ import clsx from 'clsx' import { ComponentProps } from 'react' import { useIsCreatorSpace } from 'src/rtk/features/creators/creatorsListHooks' import { useFetchStakeData } from 'src/rtk/features/creators/stakesHooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' import { useMyAddress } from '../auth/MyAccountsContext' import CreatePostCard from './cards/CreatePostCard' import CreatorInfoCard from './cards/CreatorInfoCard' -import GetMoreSubCard from './cards/GetMoreSubCard' import MyStakeCard from './cards/MyStakeCard' import StakeSubCard from './cards/StakeSubCard' import SupportCreatorsCard from './cards/SupportCreatorsCard' +import CreatorRewardInfoCard from './creator-rewards/CreatorRewardInfoCard' +import StakerRewardInfoCard from './staker-rewards/StakerRewardInfoCard' export type CreatorDashboardHomeVariant = 'posts' | 'spaces' export type CreatorDashboardSidebarType = @@ -44,61 +46,75 @@ export default function CreatorDashboardSidebar({ } function HomePageSidebar({ variant }: Extract) { - return ( - <> - - - - ) + const myAddress = useMyAddress() ?? '' + const { data, loading } = useFetchTotalStake(myAddress) + + if (loading) return null + if (data?.hasStaked) + return ( + <> + + + + + ) + return } function SpacePageSidebar({ space }: Extract) { - const myAddress = useMyAddress() - const { data } = useFetchStakeData(myAddress ?? '', space.id) - const { isCreatorSpace, loading } = useIsCreatorSpace(space.id) + const myAddress = useMyAddress() ?? '' + const { data: stakeData, loading: loadingStakeData } = useFetchStakeData(myAddress, space.id) + const { isCreatorSpace, loading: loadingIsCreator } = useIsCreatorSpace(space.id) + const { data: totalStake, loading: loadingTotalStake } = useFetchTotalStake(myAddress) - if (loading) { + if (loadingIsCreator || loadingStakeData) { return null } - if (!isCreatorSpace) { - return + const renderTopCard = () => { + if (!isCreatorSpace) { + if (!totalStake?.hasStaked) return + return null + } + + if (stakeData?.hasStaked) return + else return } - return data?.hasStaked ? ( - <> - - - - ) : ( + return ( <> - + {renderTopCard()} + {!loadingTotalStake && totalStake?.hasStaked && ( + <> + + + + )} ) } function PostPageSidebar({ space }: Extract) { - const myAddress = useMyAddress() - const { data, loading } = useFetchStakeData(myAddress ?? '', space.id) - const { isCreatorSpace, loading: loadingCreator } = useIsCreatorSpace(space.id) + const myAddress = useMyAddress() ?? '' + const { data, loading: loadingTotalStake } = useFetchTotalStake(myAddress) + const { loading: loadingCreator } = useIsCreatorSpace(space.id) if (loadingCreator) { return null } - if (!isCreatorSpace) { - return ( - <> - - - - ) - } - return ( <> - - {loading ? null : data?.hasStaked ? : } + + {!loadingTotalStake && + (data?.hasStaked ? ( + <> + + + + ) : ( + + ))} ) } diff --git a/src/components/creators/MobileIncreaseSubRewards.module.sass b/src/components/creators/MobileIncreaseSubRewards.module.sass deleted file mode 100644 index cee1bd0bf..000000000 --- a/src/components/creators/MobileIncreaseSubRewards.module.sass +++ /dev/null @@ -1,32 +0,0 @@ -@import 'src/styles/subsocial-vars.scss' - -.MobileIncreaseSubRewards - display: flex - position: relative - align-items: center - justify-content: space-between - gap: $space_normal - background: #FFEDF5 - border-radius: 0px 0px $border_radius_huge $border_radius_huge - padding: $space_small $space_normal - overflow: hidden - - .Title, .Link - font-weight: $font_weight_semibold - - .Gradient - position: absolute - background: rgba(132, 78, 247, 0.18) - top: 50% - transform: translateY(-50%) - filter: blur(130px) - left: 75% - border-radius: 50% - width: 400px - height: 400px - -.ActiveStakingBanner - background: #EDF4FF - - .Gradient - background: rgba(140, 180, 252, 0.18) diff --git a/src/components/creators/MobileIncreaseSubRewards.tsx b/src/components/creators/MobileIncreaseSubRewards.tsx deleted file mode 100644 index f16928898..000000000 --- a/src/components/creators/MobileIncreaseSubRewards.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { SpaceData } from '@subsocial/api/types' -import clsx from 'clsx' -import Link from 'next/link' -import { ComponentProps } from 'react' -import { useFetchStakeData } from 'src/rtk/features/creators/stakesHooks' -import { activeStakingLinks } from 'src/utils/links' -import { useMyAddress } from '../auth/MyAccountsContext' -import { MutedSpan } from '../utils/MutedText' -import styles from './MobileIncreaseSubRewards.module.sass' - -export type MobileIncreaseSubRewardsProps = ComponentProps<'div'> & { - space?: SpaceData - isActiveStakingBanner?: boolean -} - -export default function MobileIncreaseSubRewards(props: MobileIncreaseSubRewardsProps) { - const { space, isActiveStakingBanner } = props - const myAddress = useMyAddress() - const { data } = useFetchStakeData(myAddress ?? '', space?.id || '') - if (!data?.hasStaked && space?.id) return null - - return ( -
- - {isActiveStakingBanner ? 'Active Staking' : 'Increase SUB rewards'} - - {isActiveStakingBanner ? ( - Coming soon - ) : ( - - - Learn more - - - )} -
-
- ) -} diff --git a/src/components/creators/MobileStakerRewardDashboard.module.sass b/src/components/creators/MobileStakerRewardDashboard.module.sass new file mode 100644 index 000000000..2a4124bef --- /dev/null +++ b/src/components/creators/MobileStakerRewardDashboard.module.sass @@ -0,0 +1,97 @@ +@import 'src/styles/subsocial-vars.scss' + +.MobileStakerRewardDashboard + position: relative + + .Summary + position: relative + background: #EDF4FF + border-radius: 0px 0px $border_radius_huge $border_radius_huge + padding: $space_small $space_small $space_normal $space_normal + overflow: hidden + + .Content + display: flex + position: relative + align-items: center + justify-content: space-between + gap: $space_normal + z-index: 1 + + .Arrow + transition: transform 300ms + &.IsOpen + transform: rotate(-90deg) + + .CountProgress + transition: opacity 300ms + &.IsOpen + opacity: 0 + + .Gradient + z-index: 0 + position: absolute + background: rgba(140, 180, 252, 0.18) + top: 50% + transform: translateY(-50%) + filter: blur(130px) + left: 75% + border-radius: 50% + width: 400px + height: 400px + transition: opacity 300ms + + &.IsOpen + opacity: 0 + + .ProgressContainer + z-index: 2 + position: absolute + bottom: 0 + left: 0 + height: 6px + width: 100% + background: #CBD5E1 + + .Progress + background: #D232CF + height: 100% + border-radius: 40px + + .RewardInfo + width: 100% + position: absolute + z-index: 3 + bottom: 8px + background: #EDF4FF + overflow: clip + border-radius: 0px 0px $border_radius_huge $border_radius_huge + + transform: translateY(calc(100% - 24px)) + pointer-events: none + opacity: 0 + transition: opacity 150ms, transform 250ms + + &.IsOpen + pointer-events: initial + opacity: 1 + transform: translateY(100%) + transition: opacity 300ms, transform 150ms + + .GradientOuter + position: absolute + top: 65% + left: 20% + width: 400px + height: 400px + background: rgba(140, 180, 252, 0.3) + filter: blur(70px) + border-radius: 100% + +.StakeSubBanner + .Summary + background: #FFEDF5 + + .Content + .Gradient + background: rgba(132, 78, 247, 0.18) diff --git a/src/components/creators/MobileStakerRewardDashboard.tsx b/src/components/creators/MobileStakerRewardDashboard.tsx new file mode 100644 index 000000000..75538f8a3 --- /dev/null +++ b/src/components/creators/MobileStakerRewardDashboard.tsx @@ -0,0 +1,113 @@ +import { Tooltip } from 'antd' +import clsx from 'clsx' +import Link from 'next/link' +import { ComponentProps, useState } from 'react' +import { HiChevronRight } from 'react-icons/hi2' +import { SlQuestion } from 'react-icons/sl' +import { CREATORS_CONSTANTS } from 'src/config/constants' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useFetchUserRewardReport } from 'src/rtk/features/activeStaking/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' +import { getSubIdCreatorsLink } from 'src/utils/links' +import { useMyAddress } from '../auth/MyAccountsContext' +import styles from './MobileStakerRewardDashboard.module.sass' +import StakerRewardInfo, { StakerSuperLikeCount } from './staker-rewards/StakerRewardInfo' +import StakerRewardProgressBar from './staker-rewards/StakerRewardProgressBar' + +export type MobileStakerRewardDashboardProps = ComponentProps<'div'> + +export default function MobileStakerRewardDashboard(props: MobileStakerRewardDashboardProps) { + const { data: rewardReport, loading } = useFetchUserRewardReport() + const likesCount = rewardReport?.superLikesCount ?? 0 + + if (loading) return null + + if (!likesCount) { + return + } + return +} + +function StakeSubBanner(props: MobileStakerRewardDashboardProps) { + const sendEvent = useSendEvent() + return ( +
+ + ) +} + +function StakerRewardDashboard(props: MobileStakerRewardDashboardProps) { + const sendEvent = useSendEvent() + const { data: rewardReport } = useFetchUserRewardReport() + const likesCount = rewardReport?.superLikesCount ?? 0 + const likesToMaxReward = CREATORS_CONSTANTS.SUPER_LIKES_FOR_MAX_REWARD - likesCount + + const [isOpen, setIsOpen] = useState(false) + const myAddress = useMyAddress() + const { data } = useFetchTotalStake(myAddress ?? '') + if (!data?.hasStaked) return null + + const isOpenClassName = isOpen && styles.IsOpen + + return ( +
+
+
+ + Extra SUB rewards + 0 ? 'Daily Activity Target' : 'Daily Target Hit'}> + + + +
+
+ +
+ { + sendEvent('astake_dashboard_expanded', { + amountRange: getAmountRange(data.amount), + }) + setIsOpen(prev => !prev) + }} + className={clsx('ColorMuted FontBig', styles.Arrow, isOpenClassName)} + /> +
+
+
+ +
+
+
+
+ +
+
+
+ ) +} diff --git a/src/components/creators/cards/CreatePostCard.tsx b/src/components/creators/cards/CreatePostCard.tsx index a2965f203..038baa402 100644 --- a/src/components/creators/cards/CreatePostCard.tsx +++ b/src/components/creators/cards/CreatePostCard.tsx @@ -1,9 +1,15 @@ -import { Button } from 'antd' +import { Button, Skeleton } from 'antd' import clsx from 'clsx' import Link from 'next/link' import { HiArrowUpRight } from 'react-icons/hi2' +import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { CreatePostButtonAndModal } from 'src/components/posts/NewPostButtonInTopMenu' +import { CreateSpaceButton } from 'src/components/spaces/helpers' import { DfImage } from 'src/components/utils/DfImage' import Segment from 'src/components/utils/Segment' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useSelectSpaceIdsWhereAccountCanPostWithLoadingStatus } from 'src/rtk/app/hooks' +import { selectSpaceIdsThatCanSuggestIfSudo } from 'src/utils' import { activeStakingLinks } from 'src/utils/links' import { CreatorDashboardHomeVariant } from '../CreatorDashboardSidebar' import styles from './CreatePostCard.module.sass' @@ -13,13 +19,14 @@ export type CreatePostCardProps = { } export default function CreatePostCard({ variant }: CreatePostCardProps) { - // const myAddress = useMyAddress() + const myAddress = useMyAddress() + const sendEvent = useSendEvent() - // const { isLoading, spaceIds: ids } = - // useSelectSpaceIdsWhereAccountCanPostWithLoadingStatus(myAddress) - // const spaceIds = selectSpaceIdsThatCanSuggestIfSudo({ myAddress, spaceIds: ids }) + const { isLoading, spaceIds: ids } = + useSelectSpaceIdsWhereAccountCanPostWithLoadingStatus(myAddress) + const spaceIds = selectSpaceIdsThatCanSuggestIfSudo({ myAddress, spaceIds: ids }) - // const anySpace = spaceIds[0] + const anySpace = spaceIds[0] let imagePath = '/images/creators/active-staking.jpeg' if (variant === 'spaces') imagePath = '/images/creators/registered-creators.jpeg' @@ -27,29 +34,41 @@ export default function CreatePostCard({ variant }: CreatePostCardProps) { return (
- + - {variant === 'posts' ? Active Staking : Featured Creators} + {variant === 'posts' ? Earn Extra SUB : Featured Creators}
By creating new posts and liking new content of others, stakers of SUB can increase their staking rewards by 50% to 200%.{' '} - + + sendEvent('astake_banner_learn_more', { + eventSource: 'create-post-banner', + }) + } + > Learn more{' '}
- - {/* {isLoading ? ( + {isLoading ? ( ) : anySpace ? ( {onClick => ( - )} @@ -61,7 +80,7 @@ export default function CreatePostCard({ variant }: CreatePostCardProps) { Create profile
- )} */} + )}
) diff --git a/src/components/creators/cards/CreatorInfoCard.module.sass b/src/components/creators/cards/CreatorInfoCard.module.sass index 2b558830c..a3ddee054 100644 --- a/src/components/creators/cards/CreatorInfoCard.module.sass +++ b/src/components/creators/cards/CreatorInfoCard.module.sass @@ -13,11 +13,14 @@ margin-bottom: $space_small .Title - font-size: $font_large + font-size: $font_semilarge font-weight: $font_weight_semibold line-height: normal - margin-bottom: $space_mini .Subtitle opacity: 0.8 font-size: $font_small + + .MyStake + padding-top: $space_tiny + border-top: 1px solid #E2E8F0 diff --git a/src/components/creators/cards/CreatorInfoCard.tsx b/src/components/creators/cards/CreatorInfoCard.tsx index fdd0e283e..a9ad34a5d 100644 --- a/src/components/creators/cards/CreatorInfoCard.tsx +++ b/src/components/creators/cards/CreatorInfoCard.tsx @@ -1,24 +1,34 @@ import { SpaceData } from '@subsocial/api/types' import { Button } from 'antd' import clsx from 'clsx' +import { BsBoxArrowUpRight } from 'react-icons/bs' import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { FormatBalance } from 'src/components/common/balances' import { SpaceFollowersModal } from 'src/components/profiles/AccountsListModal' import { OfficialSpaceStatus, SpaceAvatar } from 'src/components/spaces/helpers' import CollapsibleParagraph from 'src/components/utils/CollapsibleParagraph/CollapsibleParagraph' import FollowSpaceButton from 'src/components/utils/FollowSpaceButton' import { Pluralize } from 'src/components/utils/Plularize' import Segment from 'src/components/utils/Segment' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useIsCreatorSpace } from 'src/rtk/features/creators/creatorsListHooks' import { useFetchStakeData } from 'src/rtk/features/creators/stakesHooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' import { getSubIdCreatorsLink } from 'src/utils/links' import styles from './CreatorInfoCard.module.sass' export type CreatorInfoCardProps = { space: SpaceData + showStakeButton?: boolean } -export default function CreatorInfoCard({ space }: CreatorInfoCardProps) { - const myAddress = useMyAddress() - const { data } = useFetchStakeData(myAddress ?? '', space.id) +export default function CreatorInfoCard({ space, showStakeButton = true }: CreatorInfoCardProps) { + const myAddress = useMyAddress() ?? '' + const { isCreatorSpace } = useIsCreatorSpace(space.id) + const { data: stakeData } = useFetchStakeData(myAddress, space.id) + const { data: totalStake } = useFetchTotalStake(myAddress) + const sendEvent = useSendEvent() return ( @@ -42,15 +52,69 @@ export default function CreatorInfoCard({ space }: CreatorInfoCardProps) { />
- -
- {data?.hasStaked && ( - + )} +
+ sendEvent('follow', { + spaceId: space.id, + eventSource: 'post', + amountRange: getAmountRange(totalStake?.amount), + }) + } + > + +
+
+ ) : ( +
+
+ My Stake + + + +
+ - )} - -
+
+ )} ) } diff --git a/src/components/creators/cards/GetMoreSubCard.tsx b/src/components/creators/cards/GetMoreSubCard.tsx index bf892d350..233e30f28 100644 --- a/src/components/creators/cards/GetMoreSubCard.tsx +++ b/src/components/creators/cards/GetMoreSubCard.tsx @@ -3,16 +3,19 @@ import clsx from 'clsx' import { ComponentProps } from 'react' import { DfImage } from 'src/components/utils/DfImage' import Segment from 'src/components/utils/Segment' +import { useSendEvent } from 'src/providers/AnalyticContext' import { activeStakingLinks } from 'src/utils/links' import styles from './GetMoreSubCard.module.sass' export type GetMoreSubCardProps = ComponentProps<'div'> export default function GetMoreSubCard({ ...props }: GetMoreSubCardProps) { + const sendEvent = useSendEvent() + return (
- +

Get more SUB with Active Staking

Get rewarded based on your social activity

@@ -24,6 +27,7 @@ export default function GetMoreSubCard({ ...props }: GetMoreSubCardProps) { block href={activeStakingLinks.learnMore} target='_blank' + onClick={() => sendEvent('astake_banner_learn_more', { eventSource: 'getMoreSubCard' })} > How does it work? diff --git a/src/components/creators/cards/MyStakeCard.tsx b/src/components/creators/cards/MyStakeCard.tsx index 4dccc1dd2..73bdc82c9 100644 --- a/src/components/creators/cards/MyStakeCard.tsx +++ b/src/components/creators/cards/MyStakeCard.tsx @@ -9,7 +9,10 @@ import { FormatBalance } from 'src/components/common/balances' import { useResponsiveSize } from 'src/components/responsive' import { DfImage } from 'src/components/utils/DfImage' import Segment from 'src/components/utils/Segment' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useFetchStakeData } from 'src/rtk/features/creators/stakesHooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' import { getSubIdCreatorsLink } from 'src/utils/links' import styles from './MyStakeCard.module.sass' @@ -18,9 +21,11 @@ export type MyStakeCardProps = { } export default function MyStakeCard({ space }: MyStakeCardProps) { - const myAddress = useMyAddress() - const { data, loading } = useFetchStakeData(myAddress ?? '', space.id) + const myAddress = useMyAddress() ?? '' + const { data, loading } = useFetchStakeData(myAddress, space.id) const { isMobile } = useResponsiveSize() + const sendEvent = useSendEvent() + const { data: totalStake } = useFetchTotalStake(myAddress) return ( @@ -28,11 +33,15 @@ export default function MyStakeCard({ space }: MyStakeCardProps) { )}
) : ( - + )}
diff --git a/src/components/creators/cards/SupportCreatorsCard.tsx b/src/components/creators/cards/SupportCreatorsCard.tsx index 41a268e53..79b67b211 100644 --- a/src/components/creators/cards/SupportCreatorsCard.tsx +++ b/src/components/creators/cards/SupportCreatorsCard.tsx @@ -1,23 +1,36 @@ import { Button } from 'antd' import clsx from 'clsx' import { DfImage } from 'src/components/utils/DfImage' +import { useSendEvent } from 'src/providers/AnalyticContext' import { getSubIdCreatorsLink } from 'src/utils/links' import styles from './SupportCreatorsCard.module.sass' export default function SupportCreatorsCard() { + const sendEvent = useSendEvent() return (
- +

Support creators
and earn SUB

- Generate rewards for both you and your favorite creators by staking towards them + Generate rewards for both you and creators by staking towards them

-
diff --git a/src/components/creators/common/NumberSkeleton.tsx b/src/components/creators/common/NumberSkeleton.tsx new file mode 100644 index 000000000..bc5c57846 --- /dev/null +++ b/src/components/creators/common/NumberSkeleton.tsx @@ -0,0 +1,19 @@ +import { Skeleton } from 'antd' + +export default function NumberSkeleton() { + return ( +
+ +
+ ) +} diff --git a/src/components/creators/creator-rewards/CreatorRewardInfoCard.module.sass b/src/components/creators/creator-rewards/CreatorRewardInfoCard.module.sass new file mode 100644 index 000000000..c4dbffb33 --- /dev/null +++ b/src/components/creators/creator-rewards/CreatorRewardInfoCard.module.sass @@ -0,0 +1,32 @@ +@import 'src/styles/subsocial-vars.scss' + +.CreatorRewardInfoCard + display: flex + flex-direction: column + padding: 0 + border-radius: $border_radius_big + overflow: clip + + .TopSection + padding: $space_normal + border-bottom: 1px solid #E2E8F0 + position: relative + overflow: hidden + + .Title + font-size: $font_large + font-weight: $font_weight_semibold + + .Link + font-size: $font_small + + .Image + position: absolute + top: -$space_tiny + right: -$space_tiny + height: 100% + width: 85px + + * + height: 100% + object-fit: contain diff --git a/src/components/creators/creator-rewards/CreatorRewardInfoCard.tsx b/src/components/creators/creator-rewards/CreatorRewardInfoCard.tsx new file mode 100644 index 000000000..3e1dc2e8d --- /dev/null +++ b/src/components/creators/creator-rewards/CreatorRewardInfoCard.tsx @@ -0,0 +1,98 @@ +import { Tooltip } from 'antd' +import clsx from 'clsx' +import Link from 'next/link' +import { SlQuestion } from 'react-icons/sl' +import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { FormatBalance } from 'src/components/common/balances' +import { DfImage } from 'src/components/utils/DfImage' +import { MutedSpan } from 'src/components/utils/MutedText' +import { Pluralize } from 'src/components/utils/Plularize' +import Segment from 'src/components/utils/Segment' +import { CREATORS_CONSTANTS } from 'src/config/constants' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useFetchUserRewardReport } from 'src/rtk/features/activeStaking/hooks' +import { activeStakingLinks } from 'src/utils/links' +import NumberSkeleton from '../common/NumberSkeleton' +import styles from './CreatorRewardInfoCard.module.sass' + +export default function CreatorRewardInfoCard() { + const sendEvent = useSendEvent() + const myAddress = useMyAddress() ?? '' + const { data: rewardReport, loading } = useFetchUserRewardReport(myAddress) + + if (loading || !rewardReport?.receivedLikes) return null + + return ( + + +
+
+
+
+ Received likes + + + +
+ + {loading ? : {rewardReport.receivedLikes}} + +
+
+
+ Earned from posts + + + +
+ + {loading ? ( + + ) : ( + + {' '} + + + )} + +
+
+
+ Distribution in + + + +
+ + + +
+
+
+
+ ) +} diff --git a/src/components/creators/staker-rewards/StakerRewardHistoryModal.tsx b/src/components/creators/staker-rewards/StakerRewardHistoryModal.tsx new file mode 100644 index 000000000..ba2d574a1 --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardHistoryModal.tsx @@ -0,0 +1,38 @@ +import { ModalProps, Skeleton } from 'antd' +import { FormatBalance } from 'src/components/common/balances' +import { formatDate } from 'src/components/utils' +import CustomModal from 'src/components/utils/CustomModal' +import { useFetchUserRewardHistory } from 'src/rtk/features/activeStaking/hooks' + +export type StakerRewardHistoryModalProps = Pick + +export default function StakerRewardHistoryModal({ + onCancel, + visible, +}: StakerRewardHistoryModalProps) { + const { data, loading } = useFetchUserRewardHistory(undefined, { enabled: visible }) + return ( + +
+ {(() => { + if (loading) return + if (data?.rewards.length === 0) return No rewards yet + return data?.rewards.map(reward => ( +
+ + {formatDate(reward.startDate, 'DD.MM.YY')} -{' '} + {formatDate(reward.endDate, 'DD.MM.YY')} + + + + + +
+ )) + })()} +
+
+ ) +} diff --git a/src/components/creators/staker-rewards/StakerRewardInfo.module.sass b/src/components/creators/staker-rewards/StakerRewardInfo.module.sass new file mode 100644 index 000000000..409885110 --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardInfo.module.sass @@ -0,0 +1,21 @@ +@import 'src/styles/subsocial-vars.scss' + +.StakerRewardInfo + padding: $space_normal + + .Goal + display: flex + flex-direction: column + + .GoalInfo + display: flex + align-items: center + justify-content: space-between + +.Skeleton + display: flex + align-items: center + width: 100px + * + margin: 0 !important + display: block \ No newline at end of file diff --git a/src/components/creators/staker-rewards/StakerRewardInfo.tsx b/src/components/creators/staker-rewards/StakerRewardInfo.tsx new file mode 100644 index 000000000..86c84c029 --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardInfo.tsx @@ -0,0 +1,199 @@ +import { Skeleton, Tooltip } from 'antd' +import clsx from 'clsx' +import Link from 'next/link' +import { ComponentProps, useState } from 'react' +import { RiHistoryFill } from 'react-icons/ri' +import { SlQuestion } from 'react-icons/sl' +import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { FormatBalance } from 'src/components/common/balances' +import { MutedSpan } from 'src/components/utils/MutedText' +import { Pluralize } from 'src/components/utils/Plularize' +import { CREATORS_CONSTANTS } from 'src/config/constants' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useFetchUserRewardReport } from 'src/rtk/features/activeStaking/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' +import NumberSkeleton from '../common/NumberSkeleton' +import StakerRewardHistoryModal from './StakerRewardHistoryModal' +import styles from './StakerRewardInfo.module.sass' +import StakerRewardProgressBar, { StakerRewardProgressBarProps } from './StakerRewardProgressBar' + +const { getDistributionDaysLeft, SUPER_LIKES_FOR_MAX_REWARD } = CREATORS_CONSTANTS + +export type StakerRewardInfoProps = Omit, 'size'> & + Pick + +export default function StakerRewardInfo({ size, ...props }: StakerRewardInfoProps) { + const sendEvent = useSendEvent() + const myAddress = useMyAddress() ?? '' + const { data: totalStake } = useFetchTotalStake(myAddress) + const [isOpenRewardHistoryModal, setIsOpenRewardHistoryModal] = useState(false) + const { data, loading } = useFetchUserRewardReport() + + if (loading) { + return ( +
+ +
+ ) + } + + const todayReward = data?.currentRewardAmount ?? '0' + const weekReward = data?.weeklyReward ?? '0' + + if (!(BigInt(todayReward) || BigInt(weekReward))) { + return ( +

+ Like the posts on the " + + Posts > Active Staking + + " tab to increase your staking rewards by 50-200%. +

+ ) + } + + const likeCount = data?.superLikesCount ?? 0 + const likesToMaxReward = SUPER_LIKES_FOR_MAX_REWARD - likeCount + + const dayLeftUntilDistribution = getDistributionDaysLeft() + + return ( + <> +
+
+
+
+ + {likesToMaxReward > 0 ? 'Daily Activity Target' : 'Daily Target Hit'} + + +

+ Each post you like today, up to a maximum of 10, will boost your rewards, and + reward the authors of the posts you like. +

+

+ If you like more than 10, those author rewards will then be distributed among + more authors, resulting in each author receiving fewer rewards. +

+ + } + > + +
+
+ +
+ +
+
+
+
+ Earned today + + + +
+ + {loading ? ( + + ) : ( + + {' '} + + + )} + +
+
+
+ Earned this week + + + +
+ + {loading ? ( + + ) : ( + + {' '} + + + )} + +
+
+
+ Distribution in + + + +
+ + + +
+
{ + sendEvent('astake_reward_history_opened', { + amountRange: getAmountRange(totalStake?.amount), + }) + setIsOpenRewardHistoryModal(true) + }} + style={{ cursor: 'pointer' }} + > + + Rewards History +
+
+
+ + setIsOpenRewardHistoryModal(false)} + /> + + ) +} + +export function StakerSuperLikeCount() { + const { data, loading } = useFetchUserRewardReport() + + const likeCount = data?.superLikesCount ?? 0 + + return ( + + {loading ? : {likeCount}}{' '} + likes + + ) + // const isMoreThanMax = likeCount > SUPER_LIKES_FOR_MAX_REWARD + // const surplusLike = isMoreThanMax ? likeCount - SUPER_LIKES_FOR_MAX_REWARD : 0 + + // return ( + // + // {loading ? ( + // + // ) : ( + // {Math.min(likeCount, SUPER_LIKES_FOR_MAX_REWARD)} + // )} + // {!!surplusLike && +{surplusLike}} + // + // ) +} diff --git a/src/components/creators/staker-rewards/StakerRewardInfoCard.module.sass b/src/components/creators/staker-rewards/StakerRewardInfoCard.module.sass new file mode 100644 index 000000000..3f5a27f3c --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardInfoCard.module.sass @@ -0,0 +1,32 @@ +@import 'src/styles/subsocial-vars.scss' + +.StakerRewardInfoCard + display: flex + flex-direction: column + padding: 0 + border-radius: $border_radius_big + overflow: clip + + .TopSection + padding: $space_normal + border-bottom: 1px solid #E2E8F0 + position: relative + overflow: hidden + + .Title + font-size: $font_large + font-weight: $font_weight_semibold + + .Link + font-size: $font_small + + .Image + position: absolute + top: -$space_tiny + right: -$space_tiny + height: 100% + width: 75px + + * + height: 100% + object-fit: contain diff --git a/src/components/creators/staker-rewards/StakerRewardInfoCard.tsx b/src/components/creators/staker-rewards/StakerRewardInfoCard.tsx new file mode 100644 index 000000000..b69599e26 --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardInfoCard.tsx @@ -0,0 +1,34 @@ +import clsx from 'clsx' +import Link from 'next/link' +import { DfImage } from 'src/components/utils/DfImage' +import Segment from 'src/components/utils/Segment' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { activeStakingLinks } from 'src/utils/links' +import StakerRewardInfo from './StakerRewardInfo' +import styles from './StakerRewardInfoCard.module.sass' + +export default function StakerRewardInfoCard() { + const sendEvent = useSendEvent() + return ( + + +
+ +
+
+ ) +} diff --git a/src/components/creators/staker-rewards/StakerRewardProgressBar.module.sass b/src/components/creators/staker-rewards/StakerRewardProgressBar.module.sass new file mode 100644 index 000000000..51ecdb65c --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardProgressBar.module.sass @@ -0,0 +1,7 @@ +.StakerRewardProgressBar + display: grid + transition: 500ms + gap: 2px + + :global(.ant-progress-outer), :global(.ant-progress-inner) + display: block \ No newline at end of file diff --git a/src/components/creators/staker-rewards/StakerRewardProgressBar.tsx b/src/components/creators/staker-rewards/StakerRewardProgressBar.tsx new file mode 100644 index 000000000..492908b2c --- /dev/null +++ b/src/components/creators/staker-rewards/StakerRewardProgressBar.tsx @@ -0,0 +1,56 @@ +import { Progress } from 'antd' +import clsx from 'clsx' +import { ComponentProps } from 'react' +import { CREATORS_CONSTANTS } from 'src/config/constants' +import { useFetchUserRewardReport } from 'src/rtk/features/activeStaking/hooks' +import styles from './StakerRewardProgressBar.module.sass' + +const { SUPER_LIKES_FOR_MAX_REWARD } = CREATORS_CONSTANTS + +export type StakerRewardProgressBarProps = Omit, 'size'> & { + size?: 'small' | 'default' +} + +export default function StakerRewardProgressBar({ + size = 'default', + ...props +}: StakerRewardProgressBarProps) { + const { data } = useFetchUserRewardReport() + + const likeCount = data?.superLikesCount ?? 0 + + let progress = (likeCount / SUPER_LIKES_FOR_MAX_REWARD) * 100 + let strokeColor = '#D232CF' + if (progress >= 100) { + strokeColor = '#32D255' + } + + return ( +
+ 100 ? 100 : progress} + strokeColor={strokeColor} + trailColor='#CBD5E1' + size={size} + /> + {/* {progress > 100 && ( + + )} */} +
+ ) +} diff --git a/src/components/main/HomePage.tsx b/src/components/main/HomePage.tsx index 6604e7728..0ea22da44 100644 --- a/src/components/main/HomePage.tsx +++ b/src/components/main/HomePage.tsx @@ -7,12 +7,14 @@ import { useCallback, useEffect, useState } from 'react' import config from 'src/config' import { GET_TOTAL_COUNTS } from 'src/graphql/queries' import { GetHomePageData } from 'src/graphql/__generated__/GetHomePageData' +import { useSendEvent } from 'src/providers/AnalyticContext' import { getInitialPropsWithRedux } from 'src/rtk/app' import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' import { PostKind } from 'src/types/graphql-global-types' +import { getAmountRange } from 'src/utils/analytics' import { useIsSignedIn, useMyAddress } from '../auth/MyAccountsContext' import { CreatorDashboardHomeVariant } from '../creators/CreatorDashboardSidebar' -import MobileIncreaseSubRewards from '../creators/MobileIncreaseSubRewards' +import MobileStakerRewardDashboard from '../creators/MobileStakerRewardDashboard' import { useIsMobileWidthOrDevice } from '../responsive' import { CreatorsSpaces } from '../spaces/LatestSpacesPage' import Section from '../utils/Section' @@ -65,7 +67,6 @@ const HomeTabs = (props: TabsProps) => { - @@ -120,9 +121,21 @@ const TabsHomePage = ({ const type = getFilterType(tab, typeFromUrl) const date = dateFilterOpt[dateFilterIndex].value as DateFilterType + const myAddress = useMyAddress() ?? '' + const { data: totalStake } = useFetchTotalStake(myAddress) + + const sendEvent = useSendEvent() + useEffect(() => { + sendEvent('home_page_tab_opened', { + type: tab, + value: type, + amountRange: getAmountRange(totalStake?.amount), + }) + }, [tab, type]) + useEffect(() => { let variant: CreatorDashboardHomeVariant = 'posts' - if (tab === 'spaces' || tab === 'creators') variant = 'spaces' + if (tab === 'spaces') variant = 'spaces' setCurrentTabVariant(variant) }, [setCurrentTabVariant, tab]) @@ -168,20 +181,17 @@ const TabsHomePage = ({ } }, [tab, type, date]) - const myAddress = useMyAddress() - const { data, loading } = useFetchTotalStake(myAddress ?? '') const isMobile = useIsMobileWidthOrDevice() return ( <> - {isMobile && !loading && ( - )} - + {!isMobile && }
diff --git a/src/components/main/HomePageFilters.tsx b/src/components/main/HomePageFilters.tsx index 60feab5a2..1f1f4a2c8 100644 --- a/src/components/main/HomePageFilters.tsx +++ b/src/components/main/HomePageFilters.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/router' import config from 'src/config' import LatestPostsPage from '../posts/LatestPostsPage' import { useResponsiveSize } from '../responsive/ResponsiveContext' -import LatestSpacesPage from '../spaces/LatestSpacesPage' +import LatestSpacesPage, { CreatorsSpaces } from '../spaces/LatestSpacesPage' import style from './HomePage.module.sass' import { DateFilterType, @@ -20,17 +20,19 @@ const { enableGraphQl } = config const commonFilterOption = [{ label: 'Latest', value: 'latest' }] -const offchainPostFilterOpt = enableGraphQl - ? [ - ...commonFilterOption, - { label: 'Most liked', value: 'liked' }, - { label: 'Most commented', value: 'commented' }, - ] - : [] +// const offchainPostFilterOpt = enableGraphQl +// ? [ +// ...commonFilterOption, +// { label: 'Most liked', value: 'liked' }, +// { label: 'Most commented', value: 'commented' }, +// ] +// : [] export const postFilterOpt = [ - { label: 'Recommended', value: 'suggested' }, - ...offchainPostFilterOpt, + { label: 'Active Staking', value: 'suggested' }, + { label: 'All Posts', value: 'latest' }, + // removed most liked and commented + // ...offchainPostFilterOpt, ] export const commentFilterOpt = enableGraphQl @@ -41,17 +43,18 @@ export const commentFilterOpt = enableGraphQl ] : [] -const offchainSpaceFilterOpt = enableGraphQl - ? [ - ...commonFilterOption, - { label: 'Sort by followers ', value: 'sortByFollowers' }, - { label: 'Sort by posts', value: 'sortByPosts' }, - ] - : [] +// const offchainSpaceFilterOpt = enableGraphQl +// ? [ +// ...commonFilterOption, +// { label: 'Sort by followers ', value: 'sortByFollowers' }, +// { label: 'Sort by posts', value: 'sortByPosts' }, +// ] +// : [] export const spaceFilterOpt = [ - { label: 'Polkadot Spaces', value: 'suggested' }, - ...offchainSpaceFilterOpt, + { label: 'Active Staking', value: 'suggested' }, + { label: 'Featured Creators', value: 'creators' }, + // ...offchainSpaceFilterOpt, ] export const dateFilterOpt = [ @@ -79,9 +82,10 @@ export const PostFilterView = ({ filter: { type, date }, ...props }: PostFilterP ) -export const SpaceFilterView = ({ filter: { type, date }, ...props }: SpaceFilterProps) => ( - -) +export const SpaceFilterView = ({ filter: { type, date }, ...props }: SpaceFilterProps) => { + if (type === 'creators') return + return +} const onChangeWrap = (onChange: OnChangeFn) => (e: RadioChangeEvent) => onChange(e.target.value) @@ -101,7 +105,7 @@ export const Filters = (props: Props) => { const onDateChange: any = (value: DateFilterType = 'week') => setFiltersInUrl(router, tabKey, { type: type as EntityFilter, date: value }) - const needDateFilter = !!type && type !== 'latest' && type !== 'suggested' + const needDateFilter = !!type && type !== 'latest' && type !== 'suggested' && type !== 'creators' if (!needDateFilter && !filterByKey[tabKey]?.length) return null diff --git a/src/components/main/LatestPosts.tsx b/src/components/main/LatestPosts.tsx index e76345f40..051217076 100644 --- a/src/components/main/LatestPosts.tsx +++ b/src/components/main/LatestPosts.tsx @@ -1,3 +1,4 @@ +import { useFetchMySuperLikesByPostIds } from 'src/rtk/features/activeStaking/hooks' import { useFetchMyReactionsByPostIds } from 'src/rtk/features/reactions/myPostReactionsHooks' import { PostWithAllDetails } from 'src/types' import DataList from '../lists/DataList' @@ -11,7 +12,10 @@ type Props = { export const LatestPosts = (props: Props) => { const { postsData = [], type } = props const posts = postsData.filter(x => typeof x.post.struct !== 'undefined') - useFetchMyReactionsByPostIds(posts.map(({ id }) => id)) + + const ids = posts.map(({ id }) => id) + useFetchMyReactionsByPostIds(ids) + useFetchMySuperLikesByPostIds(ids) if (posts.length === 0) { return null diff --git a/src/components/main/types.ts b/src/components/main/types.ts index 509516a48..194f743f6 100644 --- a/src/components/main/types.ts +++ b/src/components/main/types.ts @@ -4,9 +4,11 @@ import { Dispatch } from 'react' import { AccountId } from 'src/types' import { PostKind } from '../../types/graphql-global-types' -export type PostFilterType = 'latest' | 'suggested' | 'liked' | 'commented' +export type PostFilterType = 'latest' | 'suggested' +// | 'liked' | 'commented' // removed most liked and commented -export type SpaceFilterType = 'latest' | 'suggested' | 'sortByPosts' | 'sortByFollowers' +export type SpaceFilterType = 'suggested' | 'creators' +// 'latest' | 'sortByPosts' | 'sortByFollowers' export type DateFilterType = 'day' | 'week' | 'month' | 'allTime' @@ -29,7 +31,7 @@ export type SpaceDateFilterProps = SpaceFilterProps & { filter: SpaceFilterType } -export type TabsWithoutFeed = 'posts' | 'spaces' | 'comments' | 'creators' +export type TabsWithoutFeed = 'posts' | 'spaces' | 'comments' export type TabKeys = TabsWithoutFeed | 'feed' diff --git a/src/components/main/utils.ts b/src/components/main/utils.ts index d78c50ebd..341d24334 100644 --- a/src/components/main/utils.ts +++ b/src/components/main/utils.ts @@ -37,39 +37,46 @@ const getPostsByFilter: GetEntityFilter = { month: q.GET_LATEST_POST_IDS, allTime: q.GET_LATEST_POST_IDS, }, - liked: { - day: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, - week: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, - month: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, - allTime: q.GET_MOST_LIKED_POST_IDS, - }, - commented: { - day: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, - week: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, - month: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, - allTime: q.GET_MOST_COMMENTED_POST_IDS, - }, + // removed most liked and commented + // liked: { + // day: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, + // week: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, + // month: q.GET_MOST_LIKED_POST_IDS_IN_DATE_RANGE, + // allTime: q.GET_MOST_LIKED_POST_IDS, + // }, + // commented: { + // day: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, + // week: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, + // month: q.GET_MOST_COMMENTED_POST_IDS_IN_DATE_RANGE, + // allTime: q.GET_MOST_COMMENTED_POST_IDS, + // }, } const getSpacesByFilter: GetEntityFilter> = { - latest: { + creators: { day: q.GET_LATEST_SPACE_IDS, week: q.GET_LATEST_SPACE_IDS, month: q.GET_LATEST_SPACE_IDS, allTime: q.GET_LATEST_SPACE_IDS, }, - sortByFollowers: { - day: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, - week: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, - month: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, - allTime: q.GET_MOST_FOLLOWED_SPACE_IDS, - }, - sortByPosts: { - day: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, - week: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, - month: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, - allTime: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT, - }, + // latest: { + // day: q.GET_LATEST_SPACE_IDS, + // week: q.GET_LATEST_SPACE_IDS, + // month: q.GET_LATEST_SPACE_IDS, + // allTime: q.GET_LATEST_SPACE_IDS, + // }, + // sortByFollowers: { + // day: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, + // week: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, + // month: q.GET_MOST_FOLLOWED_SPACE_IDS_IN_DATE_RANGE, + // allTime: q.GET_MOST_FOLLOWED_SPACE_IDS, + // }, + // sortByPosts: { + // day: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, + // week: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, + // month: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT_IN_DATE_RANGE, + // allTime: q.GET_SPACE_IDS_SORTED_BY_POSTS_COUNT, + // }, } export const tabs = ['feed', 'posts', 'comments', 'spaces', 'creators'] diff --git a/src/components/posts/NewPostButtonInTopMenu.tsx b/src/components/posts/NewPostButtonInTopMenu.tsx index 62f754ad8..b163969f7 100644 --- a/src/components/posts/NewPostButtonInTopMenu.tsx +++ b/src/components/posts/NewPostButtonInTopMenu.tsx @@ -2,6 +2,7 @@ import { PlusCircleOutlined } from '@ant-design/icons' import { Button, Tooltip } from 'antd' import { useRouter } from 'next/router' import { useEffect, useState } from 'react' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useSelectSpaceIdsWhereAccountCanPostWithLoadingStatus } from 'src/rtk/app/hooks' import { selectSpaceIdsThatCanSuggestIfSudo } from 'src/utils' import { useMyAddress } from '../auth/MyAccountsContext' @@ -53,6 +54,7 @@ const NewPostButtonAndModal = () => { const { isMobile } = useResponsiveSize() const [visible, setVisible] = useState(false) const { asPath } = useRouter() + const sendEvent = useSendEvent() useEffect(() => { setVisible(false) @@ -60,6 +62,7 @@ const NewPostButtonAndModal = () => { /** Go to new post form or show the space selector modal. */ const onNewPostClick = () => { + sendEvent('createpost_button_clicked', { eventSource: 'top' }) setVisible(true) } diff --git a/src/components/posts/PostStats.tsx b/src/components/posts/PostStats.tsx index fb65e04a5..95d8a59cd 100644 --- a/src/components/posts/PostStats.tsx +++ b/src/components/posts/PostStats.tsx @@ -32,15 +32,21 @@ export const StatsPanel = (props: StatsProps) => { <>
- 0 && 'DfMutedLink')}> + 0 && 'DfMutedLink')} + > - {comments} + + {comments} + { - + } diff --git a/src/components/posts/editor/FullEditor.tsx b/src/components/posts/editor/FullEditor.tsx index 1b01488eb..38b511d65 100644 --- a/src/components/posts/editor/FullEditor.tsx +++ b/src/components/posts/editor/FullEditor.tsx @@ -13,6 +13,7 @@ import MdEditor from 'src/components/utils/DfMdEditor/client' import NoData from 'src/components/utils/EmptyList' import SelectSpacePreview from 'src/components/utils/SelectSpacePreview' import TxButton from 'src/components/utils/TxButton' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useSelectSpaceIdsWhereAccountCanPost } from 'src/rtk/features/spaceIds/spaceIdsHooks' import { PostContent, SpaceId } from 'src/types' import { PostType } from '.' @@ -119,7 +120,7 @@ export type EditorProps = { setSpaceForPost: (spaceId?: string) => void initialValues: FormValues postType?: PostType - defaultSpaceId?: SpaceId + spaceForPost?: SpaceId } const FullEditor = ({ @@ -128,7 +129,7 @@ const FullEditor = ({ setSpaceForPost, initialValues, postType, - defaultSpaceId, + spaceForPost, }: EditorProps) => { const myAddress = useMyAddress() const allowedSpaceIds = useSelectSpaceIdsWhereAccountCanPost(myAddress as string) @@ -139,6 +140,11 @@ const FullEditor = ({ const [publishIsDisable, setPublishIsDisable] = useState(true) const [markdownMode, setMarkdownMode] = useState(getMarkdownModeFromLocalStore()) const { saveContent } = useAutoSaveFromForm({ entity: 'post' }) + const sendEvent = useSendEvent() + + useEffect(() => { + sendEvent('createpost_editor_mode', { value: markdownMode ? 'md' : 'html' }) + }, [markdownMode]) const type: PostType = postType || (tab?.toString() as PostType) @@ -147,7 +153,7 @@ const FullEditor = ({ handleChange() } - const defaultSpace = defaultSpaceId || allowedSpaceIds[0] + const defaultSpace = spaceForPost || allowedSpaceIds[0] useEffect(() => { setSpaceForPost(defaultSpace) @@ -258,11 +264,20 @@ const FullEditor = ({ disabled={!!postType} imageSize={32} onSelect={value => { + const id = (value as LabeledValue).value.toString() setSpaceForPost((value as LabeledValue).value.toString()) + sendEvent('createpost_space_changed', { + eventSource: 'fullEditor', + from: spaceForPost, + to: id, + }) }} />
+ sendEvent('createpost_post_published', { eventSource: 'fullEditor' }) + } size='large' type='primary' block diff --git a/src/components/posts/editor/ModalEditor.tsx b/src/components/posts/editor/ModalEditor.tsx index 9ffdad428..5d7af7fed 100644 --- a/src/components/posts/editor/ModalEditor.tsx +++ b/src/components/posts/editor/ModalEditor.tsx @@ -1,12 +1,14 @@ import { LoadingOutlined } from '@ant-design/icons' import { IpfsContent } from '@subsocial/api/substrate/wrappers' import { newLogger } from '@subsocial/utils' -import { Col, Form, Modal, ModalProps, Row } from 'antd' +import { Button, Col, Form, Modal, ModalProps, Row } from 'antd' import { LabeledValue } from 'antd/lib/select' import clsx from 'clsx' import dynamic from 'next/dynamic' +import Link from 'next/link' import { useRouter } from 'next/router' -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' +import { AiFillInfoCircle } from 'react-icons/ai' import { BiImage } from 'react-icons/bi' import { useMyAddress } from 'src/components/auth/MyAccountsContext' import { htmlToMd } from 'src/components/editor/tiptap' @@ -20,9 +22,16 @@ import { getNonEmptyPostContent } from 'src/components/utils/content' import { ButtonLink } from 'src/components/utils/CustomLinks' import SelectSpacePreview from 'src/components/utils/SelectSpacePreview' import TxButton from 'src/components/utils/TxButton' -import { useFetchSpaces, useSelectSpaceIdsWhereAccountCanPost } from 'src/rtk/app/hooks' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { + useFetchSpaces, + useSelectProfile, + useSelectSpaceIdsWhereAccountCanPost, +} from 'src/rtk/app/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' import { AnyId, DataSourceTypes, IpfsCid, PostContent } from 'src/types' import { selectSpaceIdsThatCanSuggestIfSudo } from 'src/utils' +import { activeStakingLinks, getSubIdCreatorsLink } from 'src/utils/links' import { RegularPostExt } from '.' import { fieldName, FormValues } from './Fileds' import styles from './index.module.sass' @@ -43,7 +52,16 @@ export const PostEditorModalBody = ({ closeModal }: { closeModal: () => void }) const { ipfs } = useSubsocialApi() const [IpfsCid, setIpfsCid] = useState() const [publishIsDisable, setPublishIsDisable] = useState(true) - const defaultSpace = allowedSpaceIds[0] + const sendEvent = useSendEvent() + + const profile = useSelectProfile(myAddress) + const defaultSpace = useMemo(() => { + if (profile && allowedSpaceIds.includes(profile?.id ?? '')) { + return profile?.id + } + return allowedSpaceIds[0] + }, [allowedSpaceIds, profile]) + const router = useRouter() const [spaceId, setSpaceId] = useState(defaultSpace) @@ -129,7 +147,13 @@ export const PostEditorModalBody = ({ closeModal }: { closeModal: () => void }) defaultValue={defaultSpace} imageSize={32} onSelect={value => { - setSpaceId((value as LabeledValue).value.toString()) + const newId = (value as LabeledValue).value.toString() + setSpaceId(newId) + sendEvent('createpost_space_changed', { + from: spaceId, + to: newId, + eventSource: 'fastEditor', + }) }} /> ), @@ -168,10 +192,18 @@ export const PostEditorModalBody = ({ closeModal }: { closeModal: () => void }) href='/[spaceId]/posts/new' as={`/${spaceId}/posts/new`} className={clsx('LightPinkButton', 'mr-2')} + onClick={() => + sendEvent('createpost_full_editor_opened', { eventSource: 'fastEditor' }) + } > Full Editor - + sendEvent('createpost_post_published', { eventSource: 'fastEditor' })} + type='primary' + disabled={publishIsDisable} + {...txProps} + /> @@ -182,9 +214,11 @@ export interface PostEditorModalProps extends Omit { onCancel?: () => void } export const PostEditorModal = (props: PostEditorModalProps) => { - // const myAddress = useMyAddress() - // const { data } = useFetchTotalStake(myAddress ?? '') - // const hasStaked = data?.hasStaked + const myAddress = useMyAddress() + const { data } = useFetchTotalStake(myAddress ?? '') + const hasStaked = data?.hasStaked + + const sendEvent = useSendEvent() return ( {
props.onCancel && props.onCancel()} />
- {/*
+
@@ -205,17 +239,23 @@ export const PostEditorModal = (props: PostEditorModalProps) => {
{hasStaked ? (

- You can receive extra SUB when others like your posts. Feel free to share your post to - accumulate more rewards.{' '} + You can receive extra SUB when others like your content. Share your posts around the + internet to get more exposure and rewards.{' '} - + + sendEvent('astake_banner_learn_more', { eventSource: 'fastEditor' }) + } + > How does it work?

) : (

- You can receive extra SUB when others like your posts. However, you need to first + You can receive extra SUB when others like your content. However, you need to first stake some SUB to become eligible.

)} @@ -225,7 +265,7 @@ export const PostEditorModal = (props: PostEditorModalProps) => { Stake SUB )} -
*/} +
) } diff --git a/src/components/posts/editor/index.module.sass b/src/components/posts/editor/index.module.sass index 00d010101..eb2b1e5c8 100644 --- a/src/components/posts/editor/index.module.sass +++ b/src/components/posts/editor/index.module.sass @@ -119,12 +119,15 @@ max-height: 120px overflow: auto padding-top: 0 !important + display: flex + flex-direction: column &:focus-within border-color: #f759ab box-shadow: $shadow_primary \:global .ProseMirror + flex: 1 font-size: 14px !important margin: 0 padding: 0 diff --git a/src/components/posts/editor/index.tsx b/src/components/posts/editor/index.tsx index 896a73799..26f801797 100644 --- a/src/components/posts/editor/index.tsx +++ b/src/components/posts/editor/index.tsx @@ -135,7 +135,7 @@ function EditPostForm(props: PostFormProps) { setSpaceForPost={setSpaceForPost} initialValues={initialValues} postType={postType} - defaultSpaceId={spaceId} + spaceForPost={spaceId} /> ) } diff --git a/src/components/posts/share/ShareDropdown/index.tsx b/src/components/posts/share/ShareDropdown/index.tsx index bfd3fe26d..f57fdb8b7 100644 --- a/src/components/posts/share/ShareDropdown/index.tsx +++ b/src/components/posts/share/ShareDropdown/index.tsx @@ -112,7 +112,7 @@ const ShareMenu = (props: ShareMenuProps) => { } const ShareIcon = ( - + ) export const ShareDropdown = (props: ShareMenuProps) => { diff --git a/src/components/posts/view-post/PostDropDownMenu.tsx b/src/components/posts/view-post/PostDropDownMenu.tsx index 979f6332a..500a24bfb 100644 --- a/src/components/posts/view-post/PostDropDownMenu.tsx +++ b/src/components/posts/view-post/PostDropDownMenu.tsx @@ -8,8 +8,7 @@ import { ViewOnIpfs } from 'src/components/utils' import { ButtonLink } from 'src/components/utils/CustomLinks' import { DropdownMenu } from 'src/components/utils/DropDownMenu' import { useSendEvent } from 'src/providers/AnalyticContext' -import { idToBn, PostData, SpaceStruct } from 'src/types' -import { ReactionModal } from '.' +import { PostData, SpaceStruct } from 'src/types' import { useIsMyAddress, useMyAddress } from '../../auth/MyAccountsContext' import HiddenPostButton from '../HiddenPostButton' import MovePostLink from '../MovePostLink' @@ -63,9 +62,9 @@ const InnerPostDropDownMenu: FC = props => { )} - + {/* - + */} {/* {struct.createdAtBlock && } */} diff --git a/src/components/posts/view-post/PostPage.tsx b/src/components/posts/view-post/PostPage.tsx index 87fc93e1f..b97288c0d 100644 --- a/src/components/posts/view-post/PostPage.tsx +++ b/src/components/posts/view-post/PostPage.tsx @@ -4,6 +4,7 @@ import clsx from 'clsx' import { NextPage } from 'next' import router from 'next/router' import { FC, useEffect } from 'react' +import MobileStakerRewardDashboard from 'src/components/creators/MobileStakerRewardDashboard' import { PageContent } from 'src/components/main/PageWrapper' import AuthorCard from 'src/components/profiles/address-views/AuthorCard' import { useResponsiveSize } from 'src/components/responsive' @@ -25,7 +26,6 @@ import { DfMd } from '../../utils/DfMd' import Section from '../../utils/Section' import ViewTags from '../../utils/ViewTags' import Embed, { getEmbedLinkType, getYoutubeVideoId } from '../embed/Embed' -import { StatsPanel } from '../PostStats' import ViewPostLink from '../ViewPostLink' import { HiddenPostAlert, @@ -48,7 +48,7 @@ export type PostDetailsProps = { const InnerPostPage: NextPage = props => { const { postData: initialPostData, rootPostData } = props const id = initialPostData.id - const { isNotMobile } = useResponsiveSize() + const { isNotMobile, isMobile } = useResponsiveSize() useFetchMyReactionsByPostId(id) const postData = useAppSelector(state => selectPost(state, { id })) || initialPostData @@ -158,6 +158,11 @@ const InnerPostPage: NextPage = props => { withVoteBanner creatorDashboardSidebarType={{ name: 'post-page', space }} > + {isMobile && ( + + )}
@@ -172,7 +177,7 @@ const InnerPostPage: NextPage = props => { /> {isNotMobile && (
- + {/* */}
@@ -208,17 +213,15 @@ const InnerPostPage: NextPage = props => { )} + openCommentSection()} + />
)} -
- openCommentSection()} - /> -
-
{ if (content.tweet?.id) { return (
- +
) } @@ -288,17 +287,17 @@ type PostActionsPanelProps = { } export const PostActionsPanel: FC = props => { - const { postDetails, space, withBorder, className } = props + const { postDetails, /* space, */ withBorder, className } = props const { post: { struct }, } = postDetails - const ReactionsAction = () => + const ReactionsAction = () => return (
- + {/* */}
) } diff --git a/src/components/profile-selector/AccountSelector.tsx b/src/components/profile-selector/AccountSelector.tsx index 84591eb69..f30708575 100644 --- a/src/components/profile-selector/AccountSelector.tsx +++ b/src/components/profile-selector/AccountSelector.tsx @@ -1,10 +1,9 @@ -import { Button, Divider } from 'antd' +import { Divider } from 'antd' import { useState } from 'react' import { EmailAccount } from 'src/types' import useSubsocialEffect from '../api/useSubsocialEffect' import { StepsEnum, useAuth } from '../auth/AuthContext' import { useMyAccounts, useMyAccountsContext, useMyAddress } from '../auth/MyAccountsContext' -import styles from '../auth/signIn/email/SignInModalContent.module.sass' import { ProfilePreviewByAccountId, SelectAddressPreview } from '../profiles/address-views' import SubTitle from '../utils/SubTitle' @@ -173,14 +172,8 @@ const noExtension = (onClickSignIn: () => void, onClickRegister: () => void) =>
) : (
- {`You can continue reading ${config.appName} content without signing in, however, in order to create new posts, write comments, and follow others, you will need to`} - {' '} - {"with an email address and password. If you don't already have an account, you can"} - + You can continue reading {config.appName} content without signing in, however, in order to + create new posts, write comments, and follow others, you will need to create an account.
) diff --git a/src/components/profile-selector/ActionMenu.tsx b/src/components/profile-selector/ActionMenu.tsx index a27971d2f..f7377ac06 100644 --- a/src/components/profile-selector/ActionMenu.tsx +++ b/src/components/profile-selector/ActionMenu.tsx @@ -12,10 +12,12 @@ import { Menu } from 'antd' import Link from 'next/link' import { BiUserPin } from 'react-icons/bi' import { BsCaretRight } from 'react-icons/bs' +import { LuActivity } from 'react-icons/lu' import config from 'src/config' import { useAppSelector } from 'src/rtk/app/store' import { selectProfileSpaceStructById } from 'src/rtk/features/profiles/profilesSlice' import { selectSpaceIdsWithRolesByAccount } from 'src/rtk/features/spaceIds/spaceIdsWithRolesByAccountSlice' +import { selectSpace } from 'src/rtk/features/spaces/spacesSlice' import { SpaceId } from 'src/types' import { useMyDomains } from '../../rtk/features/domains/domainHooks' import { selectSpaceIdsByOwner } from '../../rtk/features/spaceIds/ownSpaceIdsSlice' @@ -26,6 +28,7 @@ import { CreateOrEditProfileSpace, SettingsLink } from '../profiles/address-view import { SwitchProfileSpaceButton } from '../profiles/address-views/utils/SwitchProfileSpaceModal' import ViewProfileLink from '../profiles/ViewProfileLink' import { SpacesWithRolesByAccountModal } from '../spaces/AccountSpaces' +import ViewSpaceLink from '../spaces/ViewSpaceLink' import { SubIcon } from '../utils' import { useMyAccountDrawer } from './MyAccountMenu' @@ -42,6 +45,7 @@ const EditProfileIcon = const MyRolesIcon = const SettingsIcon = const MyDomainsIcon = +const MyActivityIcon = const emptyArr: SpaceId[] = [] @@ -58,7 +62,8 @@ export const ActionMenu = () => { const ownSpaceIds = useAppSelector(state => (address ? selectSpaceIdsByOwner(state, address) : [])) || [] - const { accountFollowedCount, accountFollowersCount } = profileSpaceByAccount || {} + const { accountFollowedCount, accountFollowersCount, spaceId } = profileSpaceByAccount || {} + const space = useAppSelector(state => (spaceId ? selectSpace(state, { id: spaceId }) : null)) const hasMyRoles = !!useAppSelector(state => address ? selectSpaceIdsWithRolesByAccount(state, address) : emptyArr, @@ -104,9 +109,11 @@ export const ActionMenu = () => { )} - - - + {space && ( + + + + )} @@ -135,6 +142,9 @@ export const ActionMenu = () => { )} + + + {enableEmailSettings && ( diff --git a/src/components/search/SearchInput.tsx b/src/components/search/SearchInput.tsx index 1e4635a17..0e155f9c2 100644 --- a/src/components/search/SearchInput.tsx +++ b/src/components/search/SearchInput.tsx @@ -97,7 +97,11 @@ const SearchInput = () => { }, } - sendEvent('search', { value }) + sendEvent('search', { + value, + spaceId: withSpaceFilter ? spaceId : undefined, + type: withSpaceFilter ? 'bySpace' : 'all', + }) return nonEmptyStr(value) && router.replace(queryPath, queryPath) } diff --git a/src/components/spaces/LineSpacePreview.tsx b/src/components/spaces/LineSpacePreview.tsx index 0c280c7b1..1e3aca295 100644 --- a/src/components/spaces/LineSpacePreview.tsx +++ b/src/components/spaces/LineSpacePreview.tsx @@ -4,8 +4,11 @@ import clsx from 'clsx' import capitalize from 'lodash/capitalize' import dynamic from 'next/dynamic' import React from 'react' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useSelectProfile } from 'src/rtk/app/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' import { SpaceContent, SpaceId, SpaceWithSomeDetails } from 'src/types' +import { getAmountRange } from 'src/utils/analytics' import { useSelectSpace } from '../../rtk/features/spaces/spacesHooks' import { useMyAddress } from '../auth/MyAccountsContext' import { useAmISpaceFollower } from '../utils/FollowSpaceButton' @@ -40,6 +43,8 @@ export const SpacePreview = ({ noLink, }: SpacePreviewProps) => { const address = useMyAddress() + const sendEvent = useSendEvent() + const { data: totalStake } = useFetchTotalStake(address ?? '') const { id: spaceProfileId } = useSelectProfile(address) || {} const isCurrentProfile = spaceData.id === spaceProfileId @@ -94,7 +99,19 @@ export const SpacePreview = ({ /> ) } - return + return ( +
+ sendEvent('follow', { + spaceId: space.id, + eventSource: 'home', + amountRange: getAmountRange(totalStake?.amount), + }) + } + > + +
+ ) } return currentProfileLabel })()} diff --git a/src/components/spaces/SpaceCard.tsx b/src/components/spaces/SpaceCard.tsx index 535945704..31b862a04 100644 --- a/src/components/spaces/SpaceCard.tsx +++ b/src/components/spaces/SpaceCard.tsx @@ -1,6 +1,9 @@ import { EditOutlined } from '@ant-design/icons' import CardWithContent, { CardWithContentProps } from 'src/components/utils/cards/CardWithContent' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useSelectProfile, useSelectSpace } from 'src/rtk/app/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' import { useMyAddress } from '../auth/MyAccountsContext' import { editSpaceUrl } from '../urls' import { ButtonLink } from '../utils/CustomLinks' @@ -21,6 +24,8 @@ export default function SpaceCard({ spaceId, ...props }: SpaceCardProps) { const myAddress = useMyAddress() const myProfile = useSelectProfile(myAddress) const isMySpace = useIsMySpace(spaceData?.struct) + const sendEvent = useSendEvent() + const { data: totalStake } = useFetchTotalStake(myAddress ?? '') return ( Edit ) : ( - +
+ sendEvent('follow', { + spaceId: spaceData.id, + eventSource: 'post', + amountRange: getAmountRange(totalStake?.amount), + }) + } + > + +
), ] } diff --git a/src/components/spaces/ViewSpace.tsx b/src/components/spaces/ViewSpace.tsx index 34f2f3a72..5638397f1 100644 --- a/src/components/spaces/ViewSpace.tsx +++ b/src/components/spaces/ViewSpace.tsx @@ -7,16 +7,19 @@ import React, { MouseEvent, useCallback, useState } from 'react' import { ButtonLink } from 'src/components/utils/CustomLinks' import { Segment } from 'src/components/utils/Segment' import { LARGE_AVATAR_SIZE } from 'src/config/Size.config' +import { useSendEvent } from 'src/providers/AnalyticContext' import { useSetChatEntityConfig, useSetChatOpen } from 'src/rtk/app/hooks' import { useIsCreatorSpace } from 'src/rtk/features/creators/creatorsListHooks' import { useFetchStakeData } from 'src/rtk/features/creators/stakesHooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' import { SpaceContent, SpaceData, SpaceId, SpaceStruct, SpaceWithSomeDetails } from 'src/types' +import { getAmountRange } from 'src/utils/analytics' import { useSelectProfileSpace } from '../../rtk/features/profiles/profilesHooks' import { useSelectSpace } from '../../rtk/features/spaces/spacesHooks' import { useMyAddress } from '../auth/MyAccountsContext' import MyStakeCard from '../creators/cards/MyStakeCard' import StakeSubCard from '../creators/cards/StakeSubCard' -import MobileIncreaseSubRewards from '../creators/MobileIncreaseSubRewards' +import MobileStakerRewardDashboard from '../creators/MobileStakerRewardDashboard' import MakeAsProfileModal from '../profiles/address-views/utils/MakeAsProfileModal' import { useIsMobileWidthOrDevice } from '../responsive' import { editSpaceUrl, spaceUrl } from '../urls' @@ -102,6 +105,8 @@ export const InnerViewSpace = (props: Props) => { const isMobile = useIsMobileWidthOrDevice() const address = useMyAddress() const [collapseAbout, setCollapseAbout] = useState(true) + const sendEvent = useSendEvent() + const { data: totalStake } = useFetchTotalStake(address ?? '') const spaceData = useSelectSpace(initialSpaceData?.id) const isMy = useIsMySpace(spaceData?.struct) @@ -124,7 +129,7 @@ export const InnerViewSpace = (props: Props) => { const setChatConfig = useSetChatEntityConfig() const setChatOpen = useSetChatOpen() - const { isCreatorSpace, loading } = useIsCreatorSpace(spaceData?.id) + const { isCreatorSpace } = useIsCreatorSpace(spaceData?.id) // We do not return 404 page here, because this component could be used to render a space in list. if (!spaceData) return null @@ -190,6 +195,7 @@ export const InnerViewSpace = (props: Props) => { setCollapseAbout(prev => !prev) } const toggleCreatorChat = () => { + sendEvent('creator_chat_opened', { spaceId: space.id }) setChatConfig({ entity: { data: spaceData, type: 'space' }, withFloatingButton: false }) setChatOpen(true) } @@ -219,7 +225,19 @@ export const InnerViewSpace = (props: Props) => { )} - {withFollowButton && } + {withFollowButton && ( +
+ sendEvent('follow', { + spaceId: space.id, + eventSource: 'space', + amountRange: getAmountRange(totalStake?.amount), + }) + } + > + +
+ )}
@@ -292,12 +310,14 @@ export const InnerViewSpace = (props: Props) => { ) } - const showCreatorCards = isCreatorSpace && isMobile && !loading + const showCreatorCards = isMobile return (
{showCreatorCards && ( - + )} @@ -312,10 +332,11 @@ export const InnerViewSpace = (props: Props) => { } function MobileCreatorCard({ spaceData }: { spaceData: SpaceData }) { + const { isCreatorSpace, loading: loadingIsCreator } = useIsCreatorSpace(spaceData.id) const myAddress = useMyAddress() const { data, loading } = useFetchStakeData(myAddress ?? '', spaceData.id) - if (loading) return null + if (loading || loadingIsCreator || !isCreatorSpace) return null return (
diff --git a/src/components/spaces/helpers/SpaceDropdownMenu.tsx b/src/components/spaces/helpers/SpaceDropdownMenu.tsx index 5120a0b15..5e578ce85 100644 --- a/src/components/spaces/helpers/SpaceDropdownMenu.tsx +++ b/src/components/spaces/helpers/SpaceDropdownMenu.tsx @@ -64,6 +64,7 @@ export const SpaceDropdownMenu = (props: SpaceDropDownProps) => { withFloatingButton: false, }) setChatOpen(true) + sendEvent('creator_chat_opened', { spaceId: id }) }} > Creator chat diff --git a/src/components/utils/CustomModal/index.module.sass b/src/components/utils/CustomModal/index.module.sass index df3676b35..dae05204e 100644 --- a/src/components/utils/CustomModal/index.module.sass +++ b/src/components/utils/CustomModal/index.module.sass @@ -14,13 +14,14 @@ height: 100% display: flex flex-direction: column - padding: 1.5rem 1rem + padding: $space_normal $space_small + padding-bottom: $space_large overflow: hidden > * - padding-left: 0.75rem - padding-right: 0.75rem - + padding-left: $space_small + padding-right: $space_small + .CustomModalContent display: flex flex-direction: column diff --git a/src/components/utils/CustomModal/index.tsx b/src/components/utils/CustomModal/index.tsx index e7f24a30c..b1bc6bcf2 100644 --- a/src/components/utils/CustomModal/index.tsx +++ b/src/components/utils/CustomModal/index.tsx @@ -40,7 +40,7 @@ export default function CustomModal({ {...props} > {(title || subtitle) && ( -
+

{title}

{subtitle && {subtitle}}
diff --git a/src/components/utils/DfImage.tsx b/src/components/utils/DfImage.tsx index 216eecd15..c26177123 100644 --- a/src/components/utils/DfImage.tsx +++ b/src/components/utils/DfImage.tsx @@ -6,11 +6,12 @@ type Props = { size?: string | number rounded?: boolean className?: string + preview?: boolean } // TODO: create props onError export const DfImage = (props: Props) => { - const { src, size, rounded, className } = props + const { src, size, rounded, className, preview = true } = props const style: React.CSSProperties = { width: size, height: size, @@ -18,12 +19,12 @@ export const DfImage = (props: Props) => { minHeight: size, overflow: 'hidden', borderRadius: rounded ? '50%' : undefined, - cursor: 'pointer', + cursor: preview ? 'pointer' : undefined, } return (
- +
) } diff --git a/src/components/utils/IconWithLabel.tsx b/src/components/utils/IconWithLabel.tsx index 906f9cc5f..d40a76f9d 100644 --- a/src/components/utils/IconWithLabel.tsx +++ b/src/components/utils/IconWithLabel.tsx @@ -1,22 +1,27 @@ +import clsx from 'clsx' import React from 'react' type IconWithTitleProps = { icon: JSX.Element count?: number label?: string + renderZeroCount?: boolean + renderTextIfEmpty?: boolean } export const IconWithLabel = React.memo((props: IconWithTitleProps) => { - const { icon, label, count = 0 } = props + const { icon, label, count = 0, renderZeroCount, renderTextIfEmpty } = props - const countStr = count > 0 ? count.toString() : undefined + const countStr = renderZeroCount || count > 0 ? count.toString() : undefined const text = label ? label + (countStr ? ` (${countStr})` : '') : countStr return ( <> {icon} - {text && {text}} + {(text || renderTextIfEmpty) && ( + {text ||  } + )} ) }) diff --git a/src/components/utils/datahub/subscriber.tsx b/src/components/utils/datahub/subscriber.tsx new file mode 100644 index 000000000..468e5ff4c --- /dev/null +++ b/src/components/utils/datahub/subscriber.tsx @@ -0,0 +1,23 @@ +import { useEffect, useRef } from 'react' +import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { datahubSubscriptionUrl } from 'src/config/env' +import { subscribeSuperLike } from './super-likes' + +function useDatahubSubscriber() { + const unsubRef = useRef<(() => void) | undefined>() + const myAddress = useMyAddress() + + useEffect(() => { + if (!datahubSubscriptionUrl) return + + unsubRef.current = subscribeSuperLike(myAddress) + return () => { + unsubRef.current?.() + } + }, [myAddress]) +} + +export function DatahubSubscriber() { + useDatahubSubscriber() + return null +} diff --git a/src/components/utils/datahub/super-likes.ts b/src/components/utils/datahub/super-likes.ts new file mode 100644 index 000000000..36297733a --- /dev/null +++ b/src/components/utils/datahub/super-likes.ts @@ -0,0 +1,323 @@ +import { + DataHubSubscriptionEventEnum, + SocialCallDataArgs, + socialCallName, +} from '@subsocial/data-hub-sdk' +import axios from 'axios' +import dayjs from 'dayjs' +import utc from 'dayjs/plugin/utc' +import weekOfYear from 'dayjs/plugin/weekOfYear' +import { gql } from 'graphql-request' +import { getStoreDispatcher } from 'src/rtk/app/store' +import { + AddressLikeCount, + fetchAddressLikeCounts, +} from 'src/rtk/features/activeStaking/addressLikeCountSlice' +import { CanPostSuperLiked } from 'src/rtk/features/activeStaking/canPostSuperLikedSlice' +import { RewardHistory } from 'src/rtk/features/activeStaking/rewardHistorySlice' +import { fetchRewardReport, RewardReport } from 'src/rtk/features/activeStaking/rewardReportSlice' +import { + fetchSuperLikeCounts, + SuperLikeCount, +} from 'src/rtk/features/activeStaking/superLikeCountsSlice' +import { + createSocialDataEventPayload, + DatahubParams, + datahubQueryRequest, + datahubSubscription, +} from './utils' + +dayjs.extend(utc) +dayjs.extend(weekOfYear) + +// QUERIES +const GET_SUPER_LIKE_COUNTS = gql` + query GetSuperLikeCounts($postIds: [String!]!) { + activeStakingSuperLikeCountsByPost(args: { postPersistentIds: $postIds }) { + persistentPostId + count + } + } +` +export async function getSuperLikeCounts(postIds: string[]): Promise { + const res = await datahubQueryRequest< + { + activeStakingSuperLikeCountsByPost: { + persistentPostId: string + count: number + }[] + }, + { postIds: string[] } + >({ + document: GET_SUPER_LIKE_COUNTS, + variables: { postIds }, + }) + + const resultMap = new Map() + res.activeStakingSuperLikeCountsByPost.forEach(item => + resultMap.set(item.persistentPostId, { + postId: item.persistentPostId, + count: item.count, + }), + ) + + return postIds.map(postId => resultMap.get(postId) ?? { postId, count: 0 }) +} + +const GET_ADDRESS_LIKE_COUNT_TO_POSTS = gql` + query GetAddressLikeCountToPosts($address: String!, $postIds: [String!]!) { + activeStakingSuperLikeCountsByStaker(args: { postPersistentIds: $postIds, address: $address }) { + persistentPostId + count + } + } +` +export async function getAddressLikeCountToPosts( + address: string, + postIds: string[], +): Promise { + const res = await datahubQueryRequest< + { + activeStakingSuperLikeCountsByStaker: { + persistentPostId: string + count: number + }[] + }, + { postIds: string[]; address: string } + >({ + document: GET_ADDRESS_LIKE_COUNT_TO_POSTS, + variables: { postIds, address }, + }) + + const resultMap = new Map() + res.activeStakingSuperLikeCountsByStaker.forEach(item => + resultMap.set(item.persistentPostId, { + address, + postId: item.persistentPostId, + count: item.count, + }), + ) + + return postIds.map(postId => resultMap.get(postId) ?? { address, postId, count: 0 }) +} + +const GET_CAN_POSTS_SUPER_LIKED = gql` + query GetCanPostsSuperLiked($postIds: [String!]!) { + activeStakingCanDoSuperLikeByPost(args: { postPersistentIds: $postIds }) { + persistentPostId + possible + } + } +` +export async function getCanPostsSuperLiked(postIds: string[]): Promise { + const res = await datahubQueryRequest< + { + activeStakingCanDoSuperLikeByPost: { + persistentPostId: string + possible: boolean + }[] + }, + { postIds: string[] } + >({ + document: GET_CAN_POSTS_SUPER_LIKED, + variables: { postIds }, + }) + + const resultMap = new Map() + res.activeStakingCanDoSuperLikeByPost.forEach(item => + resultMap.set(item.persistentPostId, { + postId: item.persistentPostId, + canPostSuperLiked: item.possible, + }), + ) + + return postIds.map(postId => resultMap.get(postId) ?? { postId, canPostSuperLiked: false }) +} + +const GET_REWARD_REPORT = gql` + query GetRewardReport($address: String!, $day: Int!, $week: Int!) { + activeStakingDailyStatsByStaker(args: { address: $address, dayTimestamp: $day }) { + superLikesCount + currentRewardAmount + } + activeStakingRewardsByWeek(args: { weeks: [$week], filter: { account: $address } }) { + staker + creator { + total + posts { + superLikesCount + } + } + } + } +` +function getDayAndWeekTimestamp(currentDate: Date = new Date()) { + let date = dayjs.utc(currentDate) + date = date.startOf('day') + const week = date.get('year') * 100 + date.week() + return { day: date.unix(), week } +} +export async function getRewardReport(address: string): Promise { + const res = await datahubQueryRequest< + { + activeStakingDailyStatsByStaker: { + superLikesCount: number + currentRewardAmount: string + } + activeStakingRewardsByWeek: { + staker: string + creator: { + total: string + posts: { + superLikesCount: number + }[] + } + }[] + }, + { address: string; day: number; week: number } + >({ + document: GET_REWARD_REPORT, + variables: { address, ...getDayAndWeekTimestamp() }, + }) + const weekReward = res.activeStakingRewardsByWeek?.[0] + + return { + ...res.activeStakingDailyStatsByStaker, + weeklyReward: weekReward?.staker ?? '0', + creatorReward: weekReward?.creator.total ?? '0', + receivedLikes: + weekReward?.creator.posts.reduce((acc, post) => acc + post.superLikesCount, 0) ?? 0, + address, + } +} + +const GET_REWARD_HISTORY = gql` + query GetRewardHistory($address: String!) { + activeStakingRewardsByWeek(args: { filter: { account: $address } }) { + staker + week + } + } +` +export async function getRewardHistory(address: string): Promise { + const res = await datahubQueryRequest< + { + activeStakingRewardsByWeek: { + staker: string + week: number + }[] + }, + { address: string } + >({ + document: GET_REWARD_HISTORY, + variables: { address }, + }) + + return { + address, + rewards: res.activeStakingRewardsByWeek.map(({ staker, week }) => { + const startDate = dayjs + .utc() + .year(week / 100) + .week(week % 100) + .startOf('week') + const endDate = startDate.add(1, 'week') + return { + reward: staker, + week, + startDate: startDate.toISOString(), + endDate: endDate.toISOString(), + } + }), + } +} + +// MUTATIONS +export async function createSuperLike( + params: DatahubParams>, +) { + const input = createSocialDataEventPayload( + socialCallName.synth_active_staking_create_super_like, + params, + ) + + const res = await axios.post('/api/datahub/super-likes', input) + return res.data +} + +// SUBSCRIPTION +const SUBSCRIBE_SUPER_LIKE = gql` + subscription SubscribeSuperLike { + activeStakingSuperLike { + event + entity { + staker { + id + } + post { + persistentId + } + } + } + } +` + +let isSubscribed = false +export function subscribeSuperLike(myAddress: string | undefined) { + if (isSubscribed) return + isSubscribed = true + + const client = datahubSubscription() + let unsub = client.subscribe( + { + query: SUBSCRIBE_SUPER_LIKE, + }, + { + complete: () => undefined, + next: async data => { + const eventData = data.data?.activeStakingSuperLike + if (!eventData) return + + await processSubscriptionEvent(eventData as any, myAddress) + }, + error: () => { + console.log('error subscription') + }, + }, + ) + + return () => { + unsub() + isSubscribed = false + } +} + +async function processSubscriptionEvent( + eventData: { + event: DataHubSubscriptionEventEnum + entity: { staker: { id: string }; post: { persistentId: string } } + }, + myAddress: string | undefined, +) { + if ( + eventData.event !== DataHubSubscriptionEventEnum.ACTIVE_STAKING_SUPER_LIKE_CREATED && + eventData.event !== DataHubSubscriptionEventEnum.ACTIVE_STAKING_SUPER_LIKE_STATE_UPDATED + ) + return + + const { post, staker } = eventData.entity + const dispatch = getStoreDispatcher() + if (!dispatch) throw new Error('Dispatcher not exist') + + dispatch(fetchSuperLikeCounts({ postIds: [post.persistentId], reload: true })) + if (staker.id === myAddress) { + dispatch(fetchRewardReport({ address: myAddress, reload: true })) + dispatch( + fetchAddressLikeCounts({ + address: myAddress, + postIds: [post.persistentId], + reload: true, + }), + ) + } +} diff --git a/src/components/utils/datahub/utils.ts b/src/components/utils/datahub/utils.ts new file mode 100644 index 000000000..9ed6cf8ac --- /dev/null +++ b/src/components/utils/datahub/utils.ts @@ -0,0 +1,77 @@ +import { + SocialCallDataArgs, + socialCallName, + SocialEventDataApiInput, + SocialEventDataType, + socialEventProtVersion, +} from '@subsocial/data-hub-sdk' +import { GraphQLClient, RequestOptions, Variables } from 'graphql-request' +import { Client, createClient } from 'graphql-ws' +import ws from 'isomorphic-ws' +import { datahubQueryUrl, datahubSubscriptionUrl } from 'src/config/env' +import { wait } from 'src/utils/promise' + +// QUERIES +export function datahubQueryRequest( + config: RequestOptions, +) { + if (!datahubQueryUrl) throw new Error('Datahub (Query) config is not set') + + const TIMEOUT = 10 * 1000 // 10 seconds + const client = new GraphQLClient(datahubQueryUrl, { + timeout: TIMEOUT, + ...config, + }) + + return client.request({ url: datahubQueryUrl, ...config }) +} + +// MUTATIONS +export type DatahubParams = { + address: string + + uuid?: string + timestamp?: number + + args: T +} + +export function createSocialDataEventPayload( + callName: T, + { timestamp, address, uuid, args }: DatahubParams>, +) { + const payload: SocialEventDataApiInput = { + protVersion: socialEventProtVersion['0.1'], + dataType: SocialEventDataType.offChain, + callData: { + name: callName, + signer: address || '', + args: JSON.stringify(args), + timestamp: timestamp || Date.now(), + uuid: uuid || crypto.randomUUID(), + }, + providerAddr: address, + sig: '', + } + return payload +} + +// SUBSCRIPTION +let client: Client | null = null +function getClient() { + if (!datahubSubscriptionUrl) throw new Error('Datahub (Subscription) config is not set') + if (!client) { + client = createClient({ + webSocketImpl: ws, + url: datahubSubscriptionUrl, + shouldRetry: () => true, + retryWait: async attempt => { + await wait(2 ** attempt * 1000) + }, + }) + } + return client +} +export function datahubSubscription() { + return getClient() +} diff --git a/src/components/voting/SuperLike.module.sass b/src/components/voting/SuperLike.module.sass new file mode 100644 index 000000000..58169da43 --- /dev/null +++ b/src/components/voting/SuperLike.module.sass @@ -0,0 +1,25 @@ +@import "src/styles/subsocial-vars.scss" + +.SuperLike + background: #F8FAFC + color: #7779F3 + padding: 0.2em $space_small + display: flex + align-items: center + border: none + + &:focus + color: #7779F3 + background: #F8FAFC + + &:focus-visible, &:hover + color: #7779F3 + box-shadow: 0 0 0 1px rgba(119, 121, 243, 0.5) + + &:disabled + color: $color_muted + + &.SuperLikeActive + background: linear-gradient(97deg, #8B55FD 8.3%, #7493FC 91.24%) + color: white + diff --git a/src/components/voting/SuperLike.tsx b/src/components/voting/SuperLike.tsx new file mode 100644 index 000000000..fa085a9e9 --- /dev/null +++ b/src/components/voting/SuperLike.tsx @@ -0,0 +1,264 @@ +import { PostStruct } from '@subsocial/api/types' +import { Button, ButtonProps, Image, Tooltip } from 'antd' +import clsx from 'clsx' +import dayjs from 'dayjs' +import { ComponentProps, useEffect, useState } from 'react' +import { useSendEvent } from 'src/providers/AnalyticContext' +import { useAppDispatch } from 'src/rtk/app/store' +import { + fetchAddressLikeCounts, + setAddressLikeCount, +} from 'src/rtk/features/activeStaking/addressLikeCountSlice' +import { + useCanPostSuperLiked, + useFetchUserRewardReport, + useHasISuperLikedPost, + useSuperLikeCount, +} from 'src/rtk/features/activeStaking/hooks' +import { + fetchRewardReport, + setOptimisticRewardReportChange, +} from 'src/rtk/features/activeStaking/rewardReportSlice' +import { + fetchSuperLikeCounts, + setSuperLikeCount, +} from 'src/rtk/features/activeStaking/superLikeCountsSlice' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' +import { getSubIdCreatorsLink } from 'src/utils/links' +import { useAuth } from '../auth/AuthContext' +import { useMyAddress } from '../auth/MyAccountsContext' +import { IconWithLabel } from '../utils' +import CustomModal from '../utils/CustomModal' +import { createSuperLike } from '../utils/datahub/super-likes' +import { useAmISpaceFollower } from '../utils/FollowSpaceButton' +import styles from './SuperLike.module.sass' + +export type SuperLikeProps = ButtonProps & { + post: PostStruct +} + +const FIRST_TIME_SUPERLIKE = 'df.first-time-superlike' + +export default function SuperLike({ post, ...props }: SuperLikeProps) { + const dispatch = useAppDispatch() + const myAddress = useMyAddress() + const sendEvent = useSendEvent() + + const clientCanPostSuperLiked = useClientValidationOfPostSuperLike(post.createdAtTime) + const spaceId = post.spaceId + const amIFollower = useAmISpaceFollower(spaceId) + + const canPostSuperLiked = useCanPostSuperLiked(post.id) + + const [isOpenShouldStakeModal, setIsOpenShouldStakeModal] = useState(false) + const [isOpenActiveStakingModal, setIsOpenActiveStakingModal] = useState(false) + + const { data: totalStake, loading: loadingTotalStake } = useFetchTotalStake(myAddress ?? '') + const { data: userReport } = useFetchUserRewardReport() + const count = useSuperLikeCount(post.id) + const hasILiked = useHasISuperLikedPost(post.id) + + const isMyPost = post.ownerId === myAddress + + const isActive = hasILiked + const isPostCreatedMoreThan1Week = !clientCanPostSuperLiked || !canPostSuperLiked + const isDisabled = isPostCreatedMoreThan1Week || isMyPost || loadingTotalStake + + const { openSignInModal } = useAuth() + + const onClick = async () => { + if (isActive || isDisabled) return + + if (!myAddress) { + openSignInModal() + return + } + if (!totalStake?.hasStaked) { + setIsOpenShouldStakeModal(true) + return + } + + sendEvent('like', { + postId: post.id, + value: (userReport?.superLikesCount ?? 0) + 1, + spaceId, + isFollower: amIFollower, + amountRange: getAmountRange(totalStake.amount), + }) + + try { + // set optimistic changes + dispatch(setSuperLikeCount({ postId: post.id, count: count + 1 })) + dispatch(setAddressLikeCount({ address: myAddress, postId: post.id, count: count + 1 })) + dispatch(setOptimisticRewardReportChange({ address: myAddress, superLikeCountChange: 1 })) + + await createSuperLike({ address: myAddress, args: { postId: post.id } }) + } catch (error) { + // undo the optimistic changes + dispatch(setSuperLikeCount({ postId: post.id, count: count - 1 })) + dispatch(setAddressLikeCount({ address: myAddress, postId: post.id, count: count - 1 })) + dispatch(setOptimisticRewardReportChange({ address: myAddress, superLikeCountChange: -1 })) + + // refetch the real data + dispatch(fetchSuperLikeCounts({ postIds: [post.id], reload: true })) + dispatch(fetchAddressLikeCounts({ address: myAddress, postIds: [post.id], reload: true })) + dispatch(fetchRewardReport({ address: myAddress })) + } + + if (localStorage.getItem(FIRST_TIME_SUPERLIKE) !== 'false') { + setIsOpenActiveStakingModal(true) + } + localStorage.setItem(FIRST_TIME_SUPERLIKE, 'false') + } + + const icon = ( + + ) + + let tooltipTitle = '' + if (isPostCreatedMoreThan1Week) + tooltipTitle = 'You cannot super like posts that are older than 7 days' + else if (isMyPost) tooltipTitle = 'You cannot like your own post' + + const button = ( +
+ +
+ ) + + return ( + <> + {tooltipTitle ? {button} : button} + setIsOpenShouldStakeModal(false)} + /> + setIsOpenActiveStakingModal(false)} + title='Join the Active Staking Program!' + subtitle='By confirming, you agree to participate in the Active Staking Program, where you may get SUB tokens, NFTs, or other tokens, based on your active engagement.' + > +
+ + +
+
+ + ) +} + +function Diamond({ isFilled, ...props }: ComponentProps<'svg'> & { isFilled?: boolean }) { + return ( + + + + {isFilled ? ( + <> + + + + + + + + ) : ( + + )} + + + + + + + + + ) +} + +function ShouldStakeModal({ onCancel, visible }: { visible: boolean; onCancel: () => void }) { + return ( + +
+ + +
+
+ ) +} + +function useClientValidationOfPostSuperLike(createdAtTime: number) { + const [, setState] = useState({}) + + useEffect(() => { + const interval = setInterval(() => setState({}), 5 * 1000 * 60) // refresh every 5 minutes + return () => clearInterval(interval) + }, []) + + const isPostMadeMoreThan1WeekAgo = dayjs().diff(dayjs(createdAtTime), 'day') > 7 + return !isPostMadeMoreThan1WeekAgo +} diff --git a/src/components/wallets/wallet-list/WalletList.module.sass b/src/components/wallets/wallet-list/WalletList.module.sass index b05eb313a..ddf4ebe31 100644 --- a/src/components/wallets/wallet-list/WalletList.module.sass +++ b/src/components/wallets/wallet-list/WalletList.module.sass @@ -11,6 +11,11 @@ &:hover background-color: #ffedf6 + + &.Disabled + color: $color_muted + background: transparent !important + .InstallButton padding: 0 $space_tiny diff --git a/src/components/wallets/wallet-list/WalletsList.tsx b/src/components/wallets/wallet-list/WalletsList.tsx index 40b9ff7c5..233b927fe 100644 --- a/src/components/wallets/wallet-list/WalletsList.tsx +++ b/src/components/wallets/wallet-list/WalletsList.tsx @@ -1,6 +1,7 @@ import { DownloadOutlined } from '@ant-design/icons' import { Tooltip } from 'antd' -import { useEffect, useState } from 'react' +import clsx from 'clsx' +import { useEffect, useMemo, useState } from 'react' import { StepsEnum } from 'src/components/auth/AuthContext' import { setCurrentWallet } from 'src/components/auth/utils' import config from 'src/config' @@ -57,7 +58,17 @@ const WalletList = ({ setCurrentStep }: GetWalletPorps) => { } } - const wallets = supportedWallets.map(wallet => { + const sortedSupportedWallets = useMemo(() => { + let installedWallet: (typeof supportedWallets)[number][] = [] + let notInstalledWallet: (typeof supportedWallets)[number][] = [] + supportedWallets.forEach(wallet => { + if (wallet.installed) installedWallet.push(wallet) + else notInstalledWallet.push(wallet) + }) + return [...installedWallet, ...notInstalledWallet] + }, [supportedWallets]) + + const wallets = sortedSupportedWallets.map(wallet => { const { title, logo, installed, installUrls } = wallet const onInstallButtonClick = (e: React.MouseEvent) => { @@ -65,7 +76,11 @@ const WalletList = ({ setCurrentStep }: GetWalletPorps) => { } return ( -
onClick(wallet)}> +
installed && onClick(wallet)} + >
= { appBaseUrl: process.env['NEXT_PUBLIC_APP_BASE_URL'], } -export const ampId = process.env['AMP_ID'] || '' +export const ampId = process.env['NEXT_PUBLIC_AMP_ID'] || '' + +export const serverMnemonic = process.env['SERVER_MNEMONIC'] +export const datahubQueueConfig = { + url: process.env['DATAHUB_QUEUE_URL'], + token: process.env['DATAHUB_QUEUE_TOKEN'], +} + +export const datahubQueryUrl = process.env['NEXT_PUBLIC_DATAHUB_QUERY_URL'] +export const datahubSubscriptionUrl = process.env['NEXT_PUBLIC_DATAHUB_SUBSCRIPTION_URL'] /** * Enable or disable the available features of this web app by overriding them in the .env file. diff --git a/src/pages/_app.js b/src/pages/_app.js index 113dae203..9c004a2bb 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -33,8 +33,9 @@ import config from 'src/config' import '@subsocial/definitions/interfaces/types-lookup' import '@subsocial/definitions/interfaces/augment-types' import '@subsocial/definitions/interfaces/augment-api' -import AnalyticProvider from 'src/providers/AnalyticContext' +import AnalyticProvider, { AppLaunchedEventSender } from 'src/providers/AnalyticContext' import { GoogleAnalytics } from 'nextjs-google-analytics' +import { DatahubSubscriber } from 'src/components/utils/datahub/subscriber' dayjs.extend(relativeTime) dayjs.extend(localizedFormat) @@ -73,10 +74,12 @@ function MyApp(props) { {/* */} + + diff --git a/src/pages/api/datahub/super-likes.ts b/src/pages/api/datahub/super-likes.ts new file mode 100644 index 000000000..6408b6353 --- /dev/null +++ b/src/pages/api/datahub/super-likes.ts @@ -0,0 +1,31 @@ +import { SocialEventDataApiInput } from '@subsocial/data-hub-sdk' +import { NextApiRequest, NextApiResponse } from 'next' +import { ApiResponse, handlerWrapper } from 'src/server/common' +import { createSuperLikeServer } from 'src/server/datahub-queue/super-likes' +import { z } from 'zod' + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method === 'POST') { + return POST_handler(req, res) + } + + return res.status(405).send('Method Not Allowed') +} + +export type ApiDatahubModerationBody = SocialEventDataApiInput +export type ApiDatahubModerationResponse = ApiResponse +const POST_handler = handlerWrapper({ + inputSchema: z.any(), + dataGetter: req => req.body, +})({ + allowedMethods: ['POST'], + errorLabel: 'super-likes', + handler: async (data: ApiDatahubModerationBody, _req, res) => { + await createSuperLikeServer(data) + + res.json({ + message: 'OK', + success: true, + }) + }, +}) diff --git a/src/providers/AnalyticContext.tsx b/src/providers/AnalyticContext.tsx index f1f2dda8e..8c0161713 100644 --- a/src/providers/AnalyticContext.tsx +++ b/src/providers/AnalyticContext.tsx @@ -9,7 +9,12 @@ import React, { useRef, useState, } from 'react' +import { useMyAddress } from 'src/components/auth/MyAccountsContext' import { ampId } from 'src/config/env' +import { useFetchProfileSpace } from 'src/rtk/app/hooks' +import { useFetchUserRewardReport } from 'src/rtk/features/activeStaking/hooks' +import { useFetchTotalStake } from 'src/rtk/features/creators/totalStakeHooks' +import { getAmountRange } from 'src/utils/analytics' type AnalyticContextState = { amp: BrowserClient | null @@ -22,10 +27,15 @@ const initialState: AnalyticContextState = { } export type AnalyticContextProps = { - sendEvent: (name: string, properties?: Record) => void + amp: BrowserClient | null + sendEvent: ( + name: string, + properties?: Record, + userProperties?: Record, + ) => void } -const propsStub = { sendEvent: () => undefined } +const propsStub = { sendEvent: () => undefined, amp: null } export const AnalyticContext = createContext(propsStub) export async function createAmplitudeInstance() { @@ -72,11 +82,17 @@ export function AnalyticProvider(props: React.PropsWithChildren<{}>) { const contextValue: AnalyticContextProps = useMemo(() => { return { - sendEvent: (name: string, properties?: Record) => { + amp: state.amp, + sendEvent: ( + name: string, + properties?: Record, + userProperties?: Record, + ) => { const eventProps = { event_type: name, device_id: state.deviceId, event_properties: properties, + user_properties: userProperties, } if (!state.amp) { setQueuedEvents(prev => [...prev, eventProps]) @@ -106,3 +122,34 @@ export function useBuildSendEvent(eventName: string) { } export default AnalyticProvider + +export function AppLaunchedEventSender() { + const state = useContext(AnalyticContext) + + const myAddress = useMyAddress() ?? '' + const { entity, loading: loadingProfile } = useFetchProfileSpace({ id: myAddress }) + const { data: totalStake, loading: loadingTotalStake } = useFetchTotalStake(myAddress) + const { data: rewardReport, loading: loadingRewardReport } = useFetchUserRewardReport(myAddress) + + const amp = state.amp + const hasProfile = !!entity + const hasCreatorRewards = BigInt(rewardReport?.creatorReward ?? '0') > 0 + const sentInitRef = useRef(false) + const isLoading = loadingProfile || loadingTotalStake || loadingRewardReport + useEffect(() => { + if (isLoading || sentInitRef.current) return + sentInitRef.current = true + if (!myAddress) { + state.sendEvent('app_launched') + return + } + state.sendEvent('app_launched', undefined, { + hasProfile, + stakeAmountRange: getAmountRange(totalStake?.amount), + device_id: amp?.getDeviceId(), + hasCreatorRewards, + }) + }, [hasProfile, isLoading, hasCreatorRewards, amp]) + + return null +} diff --git a/src/rtk/app/hooksCommon.ts b/src/rtk/app/hooksCommon.ts index 246ba1f46..d0255c063 100644 --- a/src/rtk/app/hooksCommon.ts +++ b/src/rtk/app/hooksCommon.ts @@ -58,11 +58,15 @@ export function useFetchWithoutApi( const isEnabled = !!enabled useEffect(() => { - if (!isEnabled) return + if (!isEnabled) { + setLoading(false) + return + } let isMounted = true setError(undefined) + setLoading(true) dispatch(fetch(args)) .catch(err => { if (isMounted) { diff --git a/src/rtk/app/rootReducer.ts b/src/rtk/app/rootReducer.ts index a9d1d2ab3..369db87e5 100644 --- a/src/rtk/app/rootReducer.ts +++ b/src/rtk/app/rootReducer.ts @@ -1,6 +1,11 @@ import { combineReducers } from '@reduxjs/toolkit' import myAccount from '../features/accounts/myAccountSlice' import spaceEditors from '../features/accounts/spaceEditorsSlice' +import addressLikeCount from '../features/activeStaking/addressLikeCountSlice' +import canPostSuperLiked from '../features/activeStaking/canPostSuperLikedSlice' +import rewardHistory from '../features/activeStaking/rewardHistorySlice' +import rewardReport from '../features/activeStaking/rewardReportSlice' +import superLikeCounts from '../features/activeStaking/superLikeCountsSlice' import chainsInfo from '../features/chainsInfo/chainsInfoSlice' import chat from '../features/chat/chatSlice' import enableConfirmation from '../features/confirmationPopup/enableConfirmationSlice' @@ -55,6 +60,11 @@ const rootReducer = combineReducers({ stakes, totalStake, creatorsList, + superLikeCounts, + addressLikeCount, + rewardReport, + rewardHistory, + canPostSuperLiked, }) export type RootState = ReturnType diff --git a/src/rtk/app/wrappers.ts b/src/rtk/app/wrappers.ts index 6fcb76ec8..32cd049fa 100644 --- a/src/rtk/app/wrappers.ts +++ b/src/rtk/app/wrappers.ts @@ -198,7 +198,7 @@ export function createSimpleFetchWrapper({ sliceName: string getCachedData: (state: RootState, args: Args) => ReturnValue | undefined saveToCacheAction: (data: ReturnValue) => any - fetchData: (args: Args) => Promise + fetchData: (args: Args, state: RootState) => Promise shouldFetchCondition?: (cachedData: ReturnValue | undefined) => boolean }) { const currentlyFetchingMap = new Map>() @@ -207,19 +207,21 @@ export function createSimpleFetchWrapper({ async (allArgs, { getState, dispatch }): Promise => { const { reload, ...args } = allArgs const id = JSON.stringify(sortKeysRecursive(args)) + + const alreadyFetchedPromise = currentlyFetchingMap.get(id) + if (alreadyFetchedPromise && !reload) return alreadyFetchedPromise + if (!reload) { const fetchedData = getCachedData(getState(), allArgs) if (fetchedData && !shouldFetchCondition?.(fetchedData)) return fetchedData } - const alreadyFetchedPromise = currentlyFetchingMap.get(id) - if (alreadyFetchedPromise) return alreadyFetchedPromise - const promise = fetchData(allArgs) + const promise = fetchData(allArgs, getState()) currentlyFetchingMap.set(id, promise) const res = await promise - currentlyFetchingMap.delete(id) await dispatch(saveToCacheAction(res)) + currentlyFetchingMap.delete(id) return promise }, diff --git a/src/rtk/features/activeStaking/addressLikeCountSlice.ts b/src/rtk/features/activeStaking/addressLikeCountSlice.ts new file mode 100644 index 000000000..c610ccc40 --- /dev/null +++ b/src/rtk/features/activeStaking/addressLikeCountSlice.ts @@ -0,0 +1,86 @@ +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' +import { getAddressLikeCountToPosts } from 'src/components/utils/datahub/super-likes' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type AddressLikeCount = { + address: string + postId: string + count: number +} + +const sliceName = 'addressLikeCount' + +export function getAddressLikeCountId({ + address, + postId, +}: Pick) { + return `${address}-${postId}` +} +const adapter = createEntityAdapter({ + selectId: data => getAddressLikeCountId(data), +}) +const selectors = adapter.getSelectors(state => state.addressLikeCount) + +export const selectAddressLikeCount = selectors.selectById +export const selectAllAddressLikeCounts = selectors.selectEntities + +function getAllPostIdsFromStore(state: RootState) { + return state.posts.ids as string[] +} +export const fetchAddressLikeCounts = createSimpleFetchWrapper< + { postIds: string[] | null; address: string }, + AddressLikeCount[] +>({ + fetchData: async function ({ postIds, address }, state) { + if (postIds === null) { + postIds = getAllPostIdsFromStore(state) + } + const entities = selectAllAddressLikeCounts(state) + const newIds = postIds.filter(postId => { + const id = getAddressLikeCountId({ address, postId }) + return !entities[id] + }) + if (!newIds.length) return [] + return await getAddressLikeCountToPosts(address, postIds) + }, + saveToCacheAction: data => slice.actions.setAddressLikeCounts(data), + getCachedData: (state, { postIds, address }) => { + if (postIds === null) { + postIds = getAllPostIdsFromStore(state) + } + + const entities = selectAllAddressLikeCounts(state) + let isEveryDataCached = true + + const postEntities: AddressLikeCount[] = [] + for (let i = 0; i < postIds.length; i++) { + const id = getAddressLikeCountId({ address, postId: postIds[i] }) + if (!entities[id]) { + isEveryDataCached = false + break + } else { + postEntities.push(entities[id]!) + } + } + + if (isEveryDataCached) { + return postEntities + } + return undefined + }, + sliceName, +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setAddressLikeCount: adapter.upsertOne, + setAddressLikeCounts: adapter.upsertMany, + }, +}) + +export const { setAddressLikeCount } = slice.actions + +export default slice.reducer diff --git a/src/rtk/features/activeStaking/canPostSuperLikedSlice.ts b/src/rtk/features/activeStaking/canPostSuperLikedSlice.ts new file mode 100644 index 000000000..9d3ef8562 --- /dev/null +++ b/src/rtk/features/activeStaking/canPostSuperLikedSlice.ts @@ -0,0 +1,60 @@ +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' +import { getCanPostsSuperLiked } from 'src/components/utils/datahub/super-likes' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type CanPostSuperLiked = { + postId: string + canPostSuperLiked: boolean +} + +const sliceName = 'canPostSuperLiked' + +const adapter = createEntityAdapter({ + selectId: data => data.postId, +}) +const selectors = adapter.getSelectors(state => state.canPostSuperLiked) + +export const selectCanPostSuperLiked = selectors.selectById +export const selectAllCanPostSuperLiked = selectors.selectEntities + +export const fetchCanPostsSuperLiked = createSimpleFetchWrapper< + { postIds: string[] }, + CanPostSuperLiked[] +>({ + fetchData: async function ({ postIds }) { + return await getCanPostsSuperLiked(postIds) + }, + saveToCacheAction: data => slice.actions.setCanPostsSuperLiked(data), + getCachedData: (state, { postIds }) => { + const entities = selectAllCanPostSuperLiked(state) + let isEveryDataCached = true + + const queriedEntities: CanPostSuperLiked[] = [] + for (let i = 0; i < postIds.length; i++) { + const postId = postIds[i] + if (!entities[postId]) { + isEveryDataCached = false + break + } else { + queriedEntities.push(entities[postId]!) + } + } + + if (isEveryDataCached) { + return queriedEntities + } + return undefined + }, + sliceName, +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setCanPostsSuperLiked: adapter.upsertMany, + }, +}) + +export default slice.reducer diff --git a/src/rtk/features/activeStaking/hooks.ts b/src/rtk/features/activeStaking/hooks.ts new file mode 100644 index 000000000..1f2a8c4a4 --- /dev/null +++ b/src/rtk/features/activeStaking/hooks.ts @@ -0,0 +1,77 @@ +import { useMyAddress } from 'src/components/auth/MyAccountsContext' +import { useFetchWithoutApi } from 'src/rtk/app/hooksCommon' +import { useAppSelector } from 'src/rtk/app/store' +import { + fetchAddressLikeCounts, + getAddressLikeCountId, + selectAddressLikeCount, +} from './addressLikeCountSlice' +import { selectCanPostSuperLiked } from './canPostSuperLikedSlice' +import { fetchRewardHistory, selectUserRewardHistory } from './rewardHistorySlice' +import { fetchRewardReport, selectUserRewardReport } from './rewardReportSlice' +import { selectPostSuperLikeCount } from './superLikeCountsSlice' + +export function useSuperLikeCount(postId: string) { + return useAppSelector(state => selectPostSuperLikeCount(state, postId)?.count ?? 0) +} + +export const useFetchMySuperLikesByPostIds = (postIds: string[]) => { + const myAddress = useMyAddress() + return useFetchWithoutApi( + fetchAddressLikeCounts, + { postIds, address: myAddress ?? '' }, + { enabled: !!myAddress && postIds.length > 0 }, + ) +} + +export function useHasISuperLikedPost(postId: string) { + const myAddress = useMyAddress() ?? '' + return useAppSelector(state => { + const entity = selectAddressLikeCount( + state, + getAddressLikeCountId({ address: myAddress, postId }), + ) + return (entity?.count ?? 0) > 0 + }) +} + +export function useCanPostSuperLiked(postId: string) { + return useAppSelector(state => { + return selectCanPostSuperLiked(state, postId)?.canPostSuperLiked ?? false + }) +} + +export function useFetchUserRewardReport(address?: string) { + const myAddress = useMyAddress() + const usedAddress = address || myAddress || '' + + const data = useAppSelector(state => selectUserRewardReport(state, usedAddress)) + const fetchData = useFetchWithoutApi( + fetchRewardReport, + { address: usedAddress }, + { enabled: !!usedAddress }, + ) + + return { + ...fetchData, + data, + } +} + +export function useFetchUserRewardHistory(address?: string, config?: { enabled?: boolean }) { + const { enabled } = config || {} + const myAddress = useMyAddress() + const usedAddress = address || myAddress || '' + + const data = useAppSelector(state => selectUserRewardHistory(state, usedAddress)) + const fetchData = useFetchWithoutApi( + fetchRewardHistory, + { address: usedAddress }, + { enabled: !!usedAddress && enabled !== false }, + ) + + return { + ...fetchData, + data, + } +} diff --git a/src/rtk/features/activeStaking/rewardHistorySlice.ts b/src/rtk/features/activeStaking/rewardHistorySlice.ts new file mode 100644 index 000000000..d24a132f2 --- /dev/null +++ b/src/rtk/features/activeStaking/rewardHistorySlice.ts @@ -0,0 +1,42 @@ +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' +import { getRewardHistory } from 'src/components/utils/datahub/super-likes' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type RewardHistory = { + address: string + rewards: { + week: number + startDate: string + endDate: string + reward: string + }[] +} + +const sliceName = 'rewardHistory' + +const adapter = createEntityAdapter({ + selectId: data => data.address, +}) +const selectors = adapter.getSelectors(state => state.rewardHistory) + +export const selectUserRewardHistory = selectors.selectById + +export const fetchRewardHistory = createSimpleFetchWrapper<{ address: string }, RewardHistory>({ + fetchData: async function ({ address }) { + return await getRewardHistory(address) + }, + saveToCacheAction: data => slice.actions.setRewardHistory(data), + getCachedData: (state, { address }) => selectUserRewardHistory(state, address), + sliceName, +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setRewardHistory: adapter.upsertOne, + }, +}) + +export default slice.reducer diff --git a/src/rtk/features/activeStaking/rewardReportSlice.ts b/src/rtk/features/activeStaking/rewardReportSlice.ts new file mode 100644 index 000000000..5a6b775a6 --- /dev/null +++ b/src/rtk/features/activeStaking/rewardReportSlice.ts @@ -0,0 +1,71 @@ +import { createEntityAdapter, createSlice, PayloadAction } from '@reduxjs/toolkit' +import { getRewardReport } from 'src/components/utils/datahub/super-likes' +import { CREATORS_CONSTANTS } from 'src/config/constants' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type RewardReport = { + superLikesCount: number + currentRewardAmount: string + weeklyReward: string + + creatorReward: string + receivedLikes: number + + address: string +} + +const sliceName = 'rewardReport' + +const adapter = createEntityAdapter({ + selectId: data => data.address, +}) +const selectors = adapter.getSelectors(state => state.rewardReport) + +export const selectUserRewardReport = selectors.selectById + +export const fetchRewardReport = createSimpleFetchWrapper<{ address: string }, RewardReport>({ + fetchData: async function ({ address }) { + return await getRewardReport(address) + }, + saveToCacheAction: data => slice.actions.setRewardReport(data), + getCachedData: (state, { address }) => selectUserRewardReport(state, address), + sliceName, +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setOptimisticRewardReportChange: ( + state, + { payload }: PayloadAction<{ address: string; superLikeCountChange: 1 | -1 }>, + ) => { + const { address, superLikeCountChange } = payload + const rewardReport = state.entities[address] + if (!rewardReport) return + + const newSuperLike = rewardReport.superLikesCount + superLikeCountChange + if (rewardReport.superLikesCount > 0) { + const rewardMultiplier = BigInt( + Math.min(newSuperLike, CREATORS_CONSTANTS.SUPER_LIKES_FOR_MAX_REWARD), + ) + + const rewardPerLike = BigInt(rewardReport.currentRewardAmount) / rewardMultiplier + const weeklyWithoutCurrentReward = + BigInt(rewardReport.weeklyReward) - BigInt(rewardReport.currentRewardAmount) + + rewardReport.currentRewardAmount = (rewardMultiplier * rewardPerLike).toString() + rewardReport.weeklyReward = ( + weeklyWithoutCurrentReward + BigInt(rewardReport.currentRewardAmount) + ).toString() + } + rewardReport.superLikesCount = newSuperLike + }, + setRewardReport: adapter.upsertOne, + }, +}) + +export const { setOptimisticRewardReportChange } = slice.actions + +export default slice.reducer diff --git a/src/rtk/features/activeStaking/superLikeCountsSlice.ts b/src/rtk/features/activeStaking/superLikeCountsSlice.ts new file mode 100644 index 000000000..8d564d368 --- /dev/null +++ b/src/rtk/features/activeStaking/superLikeCountsSlice.ts @@ -0,0 +1,63 @@ +import { createEntityAdapter, createSlice } from '@reduxjs/toolkit' +import { getSuperLikeCounts } from 'src/components/utils/datahub/super-likes' +import { RootState } from 'src/rtk/app/rootReducer' +import { createSimpleFetchWrapper } from 'src/rtk/app/wrappers' + +export type SuperLikeCount = { + postId: string + count: number +} + +const sliceName = 'superLikesCounts' + +const adapter = createEntityAdapter({ + selectId: data => data.postId, +}) +const selectors = adapter.getSelectors(state => state.superLikeCounts) + +export const selectPostSuperLikeCount = selectors.selectById +export const selectPostSuperLikeCounts = selectors.selectEntities + +export const fetchSuperLikeCounts = createSimpleFetchWrapper< + { postIds: string[] }, + SuperLikeCount[] +>({ + fetchData: async function ({ postIds }) { + return await getSuperLikeCounts(postIds) + }, + saveToCacheAction: data => slice.actions.setSuperLikeCounts(data), + getCachedData: (state, { postIds }) => { + const entities = selectPostSuperLikeCounts(state) + let isEveryDataCached = true + + const postEntities: SuperLikeCount[] = [] + for (let i = 0; i < postIds.length; i++) { + const postId = postIds[i] + if (!entities[postId]) { + isEveryDataCached = false + break + } else { + postEntities.push(entities[postId]!) + } + } + + if (isEveryDataCached) { + return postEntities + } + return undefined + }, + sliceName, +}) + +const slice = createSlice({ + name: sliceName, + initialState: adapter.getInitialState(), + reducers: { + setSuperLikeCount: adapter.upsertOne, + setSuperLikeCounts: adapter.upsertMany, + }, +}) + +export const { setSuperLikeCount } = slice.actions + +export default slice.reducer diff --git a/src/rtk/features/posts/postsSlice.ts b/src/rtk/features/posts/postsSlice.ts index 0fea53f5c..922b0e364 100644 --- a/src/rtk/features/posts/postsSlice.ts +++ b/src/rtk/features/posts/postsSlice.ts @@ -40,6 +40,9 @@ import { SpaceData, SpaceStruct, } from 'src/types' +import { fetchAddressLikeCounts } from '../activeStaking/addressLikeCountSlice' +import { fetchCanPostsSuperLiked } from '../activeStaking/canPostSuperLikedSlice' +import { fetchSuperLikeCounts } from '../activeStaking/superLikeCountsSlice' import { Content, fetchContents, selectPostContentById } from '../contents/contentsSlice' import { fetchProfileSpaces } from '../profiles/profilesSlice' import { fetchMyReactionsByPostIds } from '../reactions/myPostReactionsSlice' @@ -241,6 +244,7 @@ export const fetchPosts = createAsyncThunk[] = [] + if (withOwner) { const ids = getUniqueOwnerIds(entities) const prefetchedData = generatePrefetchData( @@ -334,6 +338,11 @@ export const fetchPosts = createAsyncThunk { } /** Select two lists of space ids: that I own, I gave any role */ -export const useSelectSpaceIdsWhereAccountCanPost = (address?: AccountId) => - useAppSelector(state => { +export const useSelectSpaceIdsWhereAccountCanPost = (address?: AccountId) => { + return useAppSelector(state => { if (!address) return [] const ownSpaceIds = selectSpaceIdsByOwner(state, address) || [] const spaceIdsWithRolesByAccount = selectSpaceIdsWithRolesByAccount(state, address) || [] + const ids = [...new Set([...ownSpaceIds, ...spaceIdsWithRolesByAccount])] + const spaces = selectSpaces(state, { ids }) + + const spacesMap = new Map() + spaces.forEach(space => spacesMap.set(space.id, space)) - return [...new Set([...ownSpaceIds, ...spaceIdsWithRolesByAccount])] + return ids.filter(id => { + const space = spacesMap.get(id) + return !space?.struct.hidden + }) }, shallowEqual) +} export const useSelectSpaceIdsWhereAccountCanPostWithLoadingStatus = (address?: AccountId) => useAppSelector(state => { diff --git a/src/server/common.ts b/src/server/common.ts new file mode 100644 index 000000000..14a3cc465 --- /dev/null +++ b/src/server/common.ts @@ -0,0 +1,94 @@ +import { Keyring } from '@polkadot/keyring' +import { waitReady } from '@polkadot/wasm-crypto' +import { NextApiRequest, NextApiResponse } from 'next' +import { serverMnemonic } from 'src/config/env' +import { z } from 'zod' + +export type ApiResponse = T & { + success: boolean + message: string + errors?: any +} + +export function handlerWrapper(config: { + inputSchema: Input | null + dataGetter: (req: NextApiRequest) => unknown +}) { + return (handlerConfig: { + errorLabel?: string + handler: ( + data: z.infer, + req: NextApiRequest, + res: NextApiResponse>, + ) => PromiseLike + allowedMethods?: ('GET' | 'POST' | 'PUT' | 'DELETE')[] + }) => { + return async (req: NextApiRequest, res: NextApiResponse>) => { + const { handler, allowedMethods, errorLabel } = handlerConfig + + if (!allowedMethods?.includes(req.method ?? ('' as any))) return res.status(404).end() + + const { dataGetter, inputSchema } = config + if (!inputSchema) { + try { + return await handler(null, req, res) + } catch (err) { + console.error(`Error in ${errorLabel || 'handler'}:`, err) + let errorMessage = '' + if (err instanceof Error) { + errorMessage = err.message + } + return res.status(500).send({ + success: false, + message: 'Internal server error', + errors: errorMessage || err, + } as ApiResponse) + } + } + + const params = inputSchema.safeParse(dataGetter(req)) + + if (!params.success) { + return res.status(400).send({ + success: false, + message: 'Invalid request body', + errors: params.error.errors, + } as ApiResponse) + } + + try { + return await handler(params.data, req, res) + } catch (err) { + console.error(`Error in ${errorLabel || 'handler'}:`, err) + let errorMessage = '' + if (err instanceof Error) { + errorMessage = err.message + } + return res.status(500).send({ + success: false, + message: 'Internal server error', + errors: errorMessage || err, + } as ApiResponse) + } + } + } +} + +export function getCommonErrorMessage(e: any, fallbackMsg = 'Error has been occurred') { + return e ? { message: fallbackMsg, ...e }.message : fallbackMsg +} + +export function convertNonce(nonce: number) { + const newNonce = new Uint8Array(24) + + newNonce[0] = nonce + + return newNonce +} + +export async function getServerAccount() { + if (!serverMnemonic) throw new Error('Server Mnemonic is not set') + const keyring = new Keyring() + await waitReady() + return keyring.addFromMnemonic(serverMnemonic, {}, 'sr25519') +} diff --git a/src/server/datahub-queue/super-likes.ts b/src/server/datahub-queue/super-likes.ts new file mode 100644 index 000000000..0cb4ea0ea --- /dev/null +++ b/src/server/datahub-queue/super-likes.ts @@ -0,0 +1,38 @@ +import { SocialCallDataArgs, SocialEventDataApiInput } from '@subsocial/data-hub-sdk' +import { gql } from 'graphql-request' +import { getSubsocialApi } from 'src/components/utils/SubsocialConnect' +import { backendSigWrapper, datahubQueueRequest } from './utils' + +const CREATE_SUPER_LIKE = gql` + mutation CreateSuperLike($createSuperLikeInput: CreateMutateActiveStakingSuperLikeInput!) { + activeStakingCreateSuperLike(args: $createSuperLikeInput) { + processed + message + } + } +` + +export async function createSuperLikeServer(input: SocialEventDataApiInput) { + const args: SocialCallDataArgs<'synth_active_staking_create_super_like'> = JSON.parse( + input.callData.args || '{}', + ) + const substrateApi = await getSubsocialApi().substrateApi + const blockHash = await substrateApi.rpc.chain.getBlockHash() + + args.blockHash = blockHash.toString() + input.callData.args = JSON.stringify(args) + + const signedPayload = await backendSigWrapper(input) + const res = await datahubQueueRequest<{ + activeStakingCreateSuperLike: { processed: boolean; message: string } + }>({ + document: CREATE_SUPER_LIKE, + variables: { + createSuperLikeInput: signedPayload, + }, + }) + if (!res.activeStakingCreateSuperLike.processed) { + console.log('throw error', res.activeStakingCreateSuperLike.message) + throw new Error(res.activeStakingCreateSuperLike.message) + } +} diff --git a/src/server/datahub-queue/utils.ts b/src/server/datahub-queue/utils.ts new file mode 100644 index 000000000..2377200a6 --- /dev/null +++ b/src/server/datahub-queue/utils.ts @@ -0,0 +1,49 @@ +import { KeyringPair } from '@polkadot/keyring/types' +import { u8aToHex } from '@polkadot/util' +import { SocialEventDataApiInput } from '@subsocial/data-hub-sdk' +import { GraphQLClient, RequestOptions, Variables } from 'graphql-request' +import sortKeysRecursive from 'sort-keys-recursive' +import { datahubQueueConfig } from 'src/config/env' +import { getServerAccount } from '../common' + +export function datahubQueueRequest( + config: RequestOptions, +) { + const { url, token } = datahubQueueConfig || {} + if (!url) throw new Error('Datahub (Queue) config is not set') + + const TIMEOUT = 3 * 1000 // 3 seconds + const client = new GraphQLClient(url, { + timeout: TIMEOUT, + headers: { + Authorization: `Bearer ${token}`, + }, + ...config, + }) + + return client.request({ url, ...config }) +} + +export function datahubMutationWrapper Promise>(func: T) { + return async (...args: Parameters) => { + if (!datahubQueueConfig.url || !datahubQueueConfig.token) return + await func(...args) + } +} + +function signDatahubPayload(signer: KeyringPair | null, payload: { sig: string }) { + if (!signer) throw new Error('Signer is not defined') + const sortedPayload = sortKeysRecursive(payload) + const sig = signer.sign(JSON.stringify(sortedPayload)) + const hexSig = u8aToHex(sig) + payload.sig = hexSig +} +export const backendSigWrapper = async (input: SocialEventDataApiInput) => { + const signer = await getServerAccount() + if (!signer) throw new Error('Invalid Mnemonic') + + input.providerAddr = signer.address + signDatahubPayload(signer, input) + + return input +} diff --git a/src/styles/subsocial-vars.scss b/src/styles/subsocial-vars.scss index cf7c7a570..29289fa5b 100644 --- a/src/styles/subsocial-vars.scss +++ b/src/styles/subsocial-vars.scss @@ -31,7 +31,7 @@ $space_huge: 2rem; $color_page_bg: #f8fafc; $color_font_normal: #222222; -$color_muted: #8c8c8c; +$color_muted: #94a3b8; $color_light_muted: #888888; $color_semilight_border: #d6d6d6; $color_xtralight_border: #dddddd; diff --git a/src/styles/subsocial.scss b/src/styles/subsocial.scss index 1910bd160..42d3893e6 100644 --- a/src/styles/subsocial.scss +++ b/src/styles/subsocial.scss @@ -1494,7 +1494,7 @@ hr { .DfStatItem { color: $color_muted !important; - font-size: $font_normal; + font-size: $font_small; margin-right: $space_large; display: inline-block; diff --git a/src/utils/analytics.ts b/src/utils/analytics.ts new file mode 100644 index 000000000..2cdcfddca --- /dev/null +++ b/src/utils/analytics.ts @@ -0,0 +1,28 @@ +import BigNumber from 'bignumber.js' + +const TEN_BN = new BigNumber(10) + +const convertToBalanceWithDecimal = (balance: string | number, decimal: number) => + new BigNumber(balance).dividedBy(TEN_BN.pow(new BigNumber(decimal))) + +export function getAmountRange(amount: string | undefined, decimals = 10) { + if (!amount || amount === '0') return '0' + + const amountWithDecimals = convertToBalanceWithDecimal(amount, decimals) + + if (amountWithDecimals.lte(2000)) { + return 'up to 2000' + } else if (amountWithDecimals.lte(10000)) { + return 'up to 10000' + } else if (amountWithDecimals.lte(50000)) { + return 'up to 50000' + } else if (amountWithDecimals.lte(100000)) { + return 'up to 100000' + } else if (amountWithDecimals.lte(500000)) { + return 'up to 500000' + } else if (amountWithDecimals.lte(1000000)) { + return 'up to 1000000' + } else { + return 'more than 1000000' + } +} diff --git a/src/utils/links.ts b/src/utils/links.ts index b502e2e19..14a5fd8b8 100644 --- a/src/utils/links.ts +++ b/src/utils/links.ts @@ -8,7 +8,7 @@ export const getSubIdCreatorsLink = (space?: SpaceData) => `https://sub.id/creators/${space ? getSpaceHandleOrId(space.struct) : ''}` export const activeStakingLinks = { - learnMore: 'https://subsocial.network/active-staking-details', + learnMore: 'https://docs.subsocial.network/docs/basics/creator-staking/active-staking', discuss: () => { const currentWallet = getCurrentWallet() const link = 'https://grill.chat/creators/stakers-20132' diff --git a/src/utils/promise.ts b/src/utils/promise.ts new file mode 100644 index 000000000..e8dd56933 --- /dev/null +++ b/src/utils/promise.ts @@ -0,0 +1,3 @@ +export function wait(ms?: number) { + return new Promise(resolve => setTimeout(resolve, ms)) +} diff --git a/src/utils/window.ts b/src/utils/window.ts index 488e1fb3d..a07fa21f0 100644 --- a/src/utils/window.ts +++ b/src/utils/window.ts @@ -1,6 +1,13 @@ +import { isEmptyObj } from '@subsocial/utils' +import { isClientSide } from 'src/components/utils' + export function disablePageScroll() { document.body.style.overflow = 'hidden' } export function enablePageScroll() { document.body.style.overflow = 'auto' } + +export function hasInjectedWallet() { + return isClientSide() && !isEmptyObj((window as any).injectedWeb3) +} diff --git a/yarn.lock b/yarn.lock index c403f9993..280b10a54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -853,48 +853,11 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - "@ctrl/tinycolor@^3.4.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz#53fa5fe9c34faee89469e48f91d51a3766108bc8" integrity sha512-/Z3l6pXthq0JvMYdUFyX9j0MaCltlIn6mfh9jLyQwg5aPKxkyNa0PTHtU1AlFXLNk55ZuAeJRcpvq+tmLfKmaQ== -"@cypress/request@^2.88.10": - version "2.88.11" - resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.11.tgz#5a4c7399bc2d7e7ed56e92ce5acb620c8b187047" - integrity sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - http-signature "~1.3.6" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - performance-now "^2.1.0" - qs "~6.10.3" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^8.3.2" - -"@cypress/xvfb@^1.2.4": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a" - integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q== - dependencies: - debug "^3.1.0" - lodash.once "^4.1.1" - "@elastic/elasticsearch@7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-7.4.0.tgz#57f4066acf25e9d4e9b4f6376088433aae6f25d4" @@ -917,6 +880,116 @@ ts-node "^9" tslib "^2" +"@esbuild/android-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" + integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== + +"@esbuild/android-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" + integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== + +"@esbuild/android-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" + integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== + +"@esbuild/darwin-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" + integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== + +"@esbuild/darwin-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" + integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== + +"@esbuild/freebsd-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" + integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== + +"@esbuild/freebsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" + integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== + +"@esbuild/linux-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" + integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== + +"@esbuild/linux-arm@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" + integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== + +"@esbuild/linux-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" + integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== + +"@esbuild/linux-loong64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" + integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== + +"@esbuild/linux-mips64el@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" + integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== + +"@esbuild/linux-ppc64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" + integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== + +"@esbuild/linux-riscv64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" + integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== + +"@esbuild/linux-s390x@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" + integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== + +"@esbuild/linux-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" + integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== + +"@esbuild/netbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" + integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== + +"@esbuild/openbsd-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" + integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== + +"@esbuild/sunos-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" + integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== + +"@esbuild/win32-arm64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" + integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== + +"@esbuild/win32-ia32@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" + integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== + +"@esbuild/win32-x64@0.17.19": + version "0.17.19" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" + integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1048,6 +1121,18 @@ dependencies: multiformats "^9.5.4" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1611,6 +1696,11 @@ dependencies: "@babel/runtime" "^7.21.0" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" @@ -2374,11 +2464,35 @@ ipfs-http-client "56.0.3" json-stable-stringify "^1.0.2" +"@subsocial/api@^0.8.13": + version "0.8.14" + resolved "https://registry.yarnpkg.com/@subsocial/api/-/api-0.8.14.tgz#108d7827593c07090c1aca33b56113456b5428bb" + integrity sha512-xu91us11HwsJpsSULXuZLv8sH4cOw1xVN1vLKBQqJ1jaC7qsY5J0KGHA8hkT6STLWQ75tJjaxrXerPavhu/tQQ== + dependencies: + "@polkadot/api" latest + "@polkadot/types" latest + "@polkadot/types-known" latest + "@polkadot/types-support" latest + "@subsocial/definitions" latest + "@subsocial/utils" latest + axios "^0.24.0" + ipfs-http-client "56.0.3" + json-stable-stringify "^1.0.2" + "@subsocial/config@0.7.1": version "0.7.1" resolved "https://registry.yarnpkg.com/@subsocial/config/-/config-0.7.1.tgz#5dbd8dcd4540390e2c3ea4ab38466d7f5fee03b8" integrity sha512-zF+u865sZ++4+V1GRVtIeeBri+UMh6W+mVg04ysTNosk2gZ3xajv5m2EF8OdSvydrq2PSFTznSVVYGKACPNvjQ== +"@subsocial/data-hub-sdk@dappforce/subsocial-data-hub-sdk#staging": + version "0.0.23" + resolved "https://codeload.github.com/dappforce/subsocial-data-hub-sdk/tar.gz/782a0a8c687945b3ad8a290341be979b82176d45" + dependencies: + "@subsocial/api" "^0.8.13" + "@swc/core" "^1.3.55" + tsup "^6.7.0" + twitter-api-v2 "^1.15.0" + "@subsocial/definitions@0.8.10", "@subsocial/definitions@latest": version "0.8.10" resolved "https://registry.yarnpkg.com/@subsocial/definitions/-/definitions-0.8.10.tgz#8189faf1bbc805f7b163d61eb0d047b720f68fa4" @@ -2465,6 +2579,85 @@ resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.39.0.tgz#eb916ff5fea7fa02e77745823fde21af979273d2" integrity sha512-qZYpuE6n+mwew+X71dOur/CbMXj6rNW27o63JeJwdQH/GvcSKm3JLNhd+bGzwUKg0D/zD30Qc6p4JykArzM+tA== +"@swc/core-darwin-arm64@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.102.tgz#2bbd90a8751e6eee981f857ec3f0b6233208da37" + integrity sha512-CJDxA5Wd2cUMULj3bjx4GEoiYyyiyL8oIOu4Nhrs9X+tlg8DnkCm4nI57RJGP8Mf6BaXPIJkHX8yjcefK2RlDA== + +"@swc/core-darwin-x64@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.3.102.tgz#df16d51f45771d3c9cca8554b28a3190cdb075cf" + integrity sha512-X5akDkHwk6oAer49oER0qZMjNMkLH3IOZaV1m98uXIasAGyjo5WH1MKPeMLY1sY6V6TrufzwiSwD4ds571ytcg== + +"@swc/core-linux-arm-gnueabihf@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.102.tgz#eb71697590c56ea261fa9a4b198c45304c7ece39" + integrity sha512-kJH3XtZP9YQdjq/wYVBeFuiVQl4HaC4WwRrIxAHwe2OyvrwUI43dpW3LpxSggBnxXcVCXYWf36sTnv8S75o2Gw== + +"@swc/core-linux-arm64-gnu@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.102.tgz#75d72d5253d56723fa7054e1a8f313bf3d17b1a2" + integrity sha512-flQP2WDyCgO24WmKA1wjjTx+xfCmavUete2Kp6yrM+631IHLGnr17eu7rYJ/d4EnDBId/ytMyrnWbTVkaVrpbQ== + +"@swc/core-linux-arm64-musl@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.102.tgz#7db86022fec57c1e06c573d45cef5e911bcc420e" + integrity sha512-bQEQSnC44DyoIGLw1+fNXKVGoCHi7eJOHr8BdH0y1ooy9ArskMjwobBFae3GX4T1AfnrTaejyr0FvLYIb0Zkog== + +"@swc/core-linux-x64-gnu@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.102.tgz#298a25aa854924bedc7e4b69da52da19f84fc7a8" + integrity sha512-dFvnhpI478svQSxqISMt00MKTDS0e4YtIr+ioZDG/uJ/q+RpcNy3QI2KMm05Fsc8Y0d4krVtvCKWgfUMsJZXAg== + +"@swc/core-linux-x64-musl@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.102.tgz#1bcd911aaa88b96f3bb665b0fd84ef4d21adf886" + integrity sha512-+a0M3CvjeIRNA/jTCzWEDh2V+mhKGvLreHOL7J97oULZy5yg4gf7h8lQX9J8t9QLbf6fsk+0F8bVH1Ie/PbXjA== + +"@swc/core-win32-arm64-msvc@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.102.tgz#59084786364d03fa4a120bdd589a557a00caedeb" + integrity sha512-w76JWLjkZNOfkB25nqdWUNCbt0zJ41CnWrJPZ+LxEai3zAnb2YtgB/cCIrwxDebRuMgE9EJXRj7gDDaTEAMOOQ== + +"@swc/core-win32-ia32-msvc@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.102.tgz#27954889d940a63796d58ff7753f5f27ed381a1f" + integrity sha512-vlDb09HiGqKwz+2cxDS9T5/461ipUQBplvuhW+cCbzzGuPq8lll2xeyZU0N1E4Sz3MVdSPx1tJREuRvlQjrwNg== + +"@swc/core-win32-x64-msvc@1.3.102": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.102.tgz#477da542e6b01b3eb64476ec9a78f497a9b87807" + integrity sha512-E/jfSD7sShllxBwwgDPeXp1UxvIqehj/ShSUqq1pjR/IDRXngcRSXKJK92mJkNFY7suH6BcCWwzrxZgkO7sWmw== + +"@swc/core@^1.3.55": + version "1.3.102" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.3.102.tgz#870874bcf1d78cd7bb1bc66b31bf2b1a87c1a667" + integrity sha512-OAjNLY/f6QWKSDzaM3bk31A+OYHu6cPa9P/rFIx8X5d24tHXUpRiiq6/PYI6SQRjUPlB72GjsjoEU8F+ALadHg== + dependencies: + "@swc/counter" "^0.1.1" + "@swc/types" "^0.1.5" + optionalDependencies: + "@swc/core-darwin-arm64" "1.3.102" + "@swc/core-darwin-x64" "1.3.102" + "@swc/core-linux-arm-gnueabihf" "1.3.102" + "@swc/core-linux-arm64-gnu" "1.3.102" + "@swc/core-linux-arm64-musl" "1.3.102" + "@swc/core-linux-x64-gnu" "1.3.102" + "@swc/core-linux-x64-musl" "1.3.102" + "@swc/core-win32-arm64-msvc" "1.3.102" + "@swc/core-win32-ia32-msvc" "1.3.102" + "@swc/core-win32-x64-msvc" "1.3.102" + +"@swc/counter@^0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.2.tgz#bf06d0770e47c6f1102270b744e17b934586985e" + integrity sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw== + +"@swc/types@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a" + integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw== + "@testing-library/cypress@^8.0.3": version "8.0.7" resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-8.0.7.tgz#18315eba3cf8852808afadf122e4858406384015" @@ -2921,11 +3114,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.12.tgz#833756634e78c829e1254db006468dadbb0c696b" integrity sha512-Wha1UwsB3CYdqUm2PPzh/1gujGCNtWVUYF0mB00fJFoR4gTyWTDPjSm+zBF787Ahw8vSGgBja90MkgFwvB86Dg== -"@types/node@^14.14.31": - version "14.18.42" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.42.tgz#fa39b2dc8e0eba61bdf51c66502f84e23b66e114" - integrity sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg== - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -3073,16 +3261,6 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== -"@types/sinonjs__fake-timers@8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" - integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g== - -"@types/sizzle@^2.3.2": - version "2.3.3" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef" - integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ== - "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -3129,13 +3307,6 @@ dependencies: "@types/yargs-parser" "*" -"@types/yauzl@^2.9.1": - version "2.10.0" - resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" - integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw== - dependencies: - "@types/node" "*" - "@types/yup@^0.29.11": version "0.29.14" resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.14.tgz#754f1dccedcc66fc2bbe290c27f5323b407ceb00" @@ -3325,14 +3496,6 @@ agent-base@6: dependencies: debug "4" -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" @@ -3377,11 +3540,6 @@ anser@1.4.9: resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== -ansi-colors@^4.1.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" - integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== - ansi-escapes@^3.0.0, ansi-escapes@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -3409,6 +3567,11 @@ ansi-regex@^5.0.0, ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -3433,6 +3596,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansicolors@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" @@ -3520,6 +3688,11 @@ any-observable@^0.3.0: resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + any-signal@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/any-signal/-/any-signal-3.0.1.tgz#49cae34368187a3472e31de28fb5cb1430caa9a6" @@ -3767,11 +3940,6 @@ apollo@^2.34.0: tty "1.0.1" vscode-uri "1.0.6" -arch@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" - integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -3897,18 +4065,6 @@ asn1.js@^5.2.0: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - assert@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" @@ -3966,7 +4122,7 @@ async-validator@^3.0.3: resolved "https://registry.yarnpkg.com/async-validator/-/async-validator-3.5.2.tgz#68e866a96824e8b2694ff7a831c1a25c44d5e500" integrity sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ== -async@^3.2.0, async@^3.2.3: +async@^3.2.3: version "3.2.4" resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== @@ -4003,16 +4159,6 @@ await-to-js@^3.0.0: resolved "https://registry.yarnpkg.com/await-to-js/-/await-to-js-3.0.0.tgz#70929994185616f4675a91af6167eb61cc92868f" integrity sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g== -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== - -aws4@^1.8.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" - integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== - axe-core@^4.6.2: version "4.7.0" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" @@ -4129,13 +4275,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -4178,16 +4317,6 @@ blob-to-it@^1.0.1: dependencies: browser-readablestream-to-it "^1.0.3" -blob-util@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" - integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== - -bluebird@^3.7.2: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - bn.js@5.2.1, bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" @@ -4350,11 +4479,6 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -4382,14 +4506,6 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" - buffer@^6.0.1, buffer@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" @@ -4410,6 +4526,13 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== +bundle-require@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/bundle-require/-/bundle-require-4.0.2.tgz#65fc74ff14eabbba36d26c9a6161bd78fff6b29e" + integrity sha512-jwzPOChofl67PSTW2SGubV9HBQAhhR2i6nskiOThauo9dzwDUgOWQScFVaJkjEfYX+UXiD+LEx8EblQMc2wIag== + dependencies: + load-tsconfig "^0.2.3" + byline@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" @@ -4420,6 +4543,11 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +cac@^6.7.12: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -4435,11 +4563,6 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" -cachedir@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" - integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw== - call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -4517,11 +4640,6 @@ case-anything@^2.1.10: resolved "https://registry.yarnpkg.com/case-anything/-/case-anything-2.1.10.tgz#d18a6ca968d54ec3421df71e3e190f3bced23410" integrity sha512-JczJwVrCP0jPKh05McyVsuOg6AYosrB9XWZKbQzXeDAm2ClE/PJE/BcrrQrVyGYH7Jg8V/LDupmyL4kFlVsVFQ== -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - cborg@^1.5.4, cborg@^1.6.0: version "1.10.1" resolved "https://registry.yarnpkg.com/cborg/-/cborg-1.10.1.tgz#24cfe52c69ec0f66f95e23dc57f2086954c8d718" @@ -4627,11 +4745,6 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -check-more-types@^2.24.0: - version "2.24.0" - resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" - integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA== - chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -4647,7 +4760,7 @@ chokidar@3.5.1: optionalDependencies: fsevents "~2.3.1" -"chokidar@>=3.0.0 <4.0.0": +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.1: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -4667,11 +4780,6 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.2.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" - integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== - cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -4712,11 +4820,6 @@ clean-css@^4.2.3: dependencies: source-map "~0.6.0" -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - clean-stack@^3.0.0, clean-stack@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-3.0.1.tgz#155bf0b2221bf5f4fba89528d24c5953f17fe3a8" @@ -4731,13 +4834,6 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-progress@^3.10.0: version "3.12.0" resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.12.0.tgz#807ee14b66bcc086258e444ad0f19e7d42577942" @@ -4745,15 +4841,6 @@ cli-progress@^3.10.0: dependencies: string-width "^4.2.3" -cli-table3@~0.6.1: - version "0.6.3" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" - integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== - dependencies: - string-width "^4.2.0" - optionalDependencies: - "@colors/colors" "1.5.0" - cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -4762,14 +4849,6 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" -cli-truncate@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" - integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== - dependencies: - slice-ansi "^3.0.0" - string-width "^4.2.0" - cli-ux@6.0.9: version "6.0.9" resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-6.0.9.tgz#b5ab690314348b45b2c7458dad7621ae1be7c61d" @@ -4888,12 +4967,7 @@ colorette@^1.2.2: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== -colorette@^2.0.16: - version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" - integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== - -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: +combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -4910,22 +4984,17 @@ commander@2, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.1.1: +commander@^4.0.0, commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== -common-tags@^1.5.1, common-tags@^1.8.0: +common-tags@^1.5.1: version "1.8.2" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== @@ -5018,11 +5087,6 @@ core-js@^3.0.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.30.1.tgz#fc9c5adcc541d8e9fa3e381179433cbf795628ba" integrity sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -5226,54 +5290,6 @@ cypress-wait-until@^1.7.2: resolved "https://registry.yarnpkg.com/cypress-wait-until/-/cypress-wait-until-1.7.2.tgz#7f534dd5a11c89b65359e7a0210f20d3dfc22107" integrity sha512-uZ+M8/MqRcpf+FII/UZrU7g1qYZ4aVlHcgyVopnladyoBrpoaMJ4PKZDrdOJ05H5RHbr7s9Tid635X3E+ZLU/Q== -cypress@^10.11.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.11.0.tgz#e9fbdd7638bae3d8fb7619fd75a6330d11ebb4e8" - integrity sha512-lsaE7dprw5DoXM00skni6W5ElVVLGAdRUUdZjX2dYsGjbY/QnpzWZ95Zom1mkGg0hAaO/QVTZoFVS7Jgr/GUPA== - dependencies: - "@cypress/request" "^2.88.10" - "@cypress/xvfb" "^1.2.4" - "@types/node" "^14.14.31" - "@types/sinonjs__fake-timers" "8.1.1" - "@types/sizzle" "^2.3.2" - arch "^2.2.0" - blob-util "^2.0.2" - bluebird "^3.7.2" - buffer "^5.6.0" - cachedir "^2.3.0" - chalk "^4.1.0" - check-more-types "^2.24.0" - cli-cursor "^3.1.0" - cli-table3 "~0.6.1" - commander "^5.1.0" - common-tags "^1.8.0" - dayjs "^1.10.4" - debug "^4.3.2" - enquirer "^2.3.6" - eventemitter2 "6.4.7" - execa "4.1.0" - executable "^4.1.1" - extract-zip "2.0.1" - figures "^3.2.0" - fs-extra "^9.1.0" - getos "^3.2.1" - is-ci "^3.0.0" - is-installed-globally "~0.4.0" - lazy-ass "^1.6.0" - listr2 "^3.8.3" - lodash "^4.17.21" - log-symbols "^4.0.0" - minimist "^1.2.6" - ospath "^1.2.2" - pretty-bytes "^5.6.0" - proxy-from-env "1.0.0" - request-progress "^3.0.0" - semver "^7.3.2" - supports-color "^8.1.1" - tmp "~0.2.1" - untildify "^4.0.0" - yauzl "^2.10.0" - d3-array@1, d3-array@~1.2.0: version "1.2.4" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f" @@ -5469,13 +5485,6 @@ dash-get@^1.0.2: resolved "https://registry.yarnpkg.com/dash-get/-/dash-get-1.0.2.tgz#4c9e9ad5ef04c4bf9d3c9a451f6f7997298dcc7c" integrity sha512-4FbVrHDwfOASx7uQVxeiCTo7ggSdYZbqs8lH+WU6ViypPlDbe9y6IP5VVUDQBv9DcnyaiPT5XT0UWHgJ64zLeQ== -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - data-uri-to-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" @@ -5505,7 +5514,7 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -dayjs@1.x, dayjs@^1.10.4, dayjs@^1.10.7, dayjs@^1.9.6: +dayjs@1.x, dayjs@^1.10.7, dayjs@^1.9.6: version "1.11.7" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2" integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ== @@ -5524,13 +5533,6 @@ debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, d dependencies: ms "2.1.2" -debug@^3.1.0: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - decamelize@^1.0.0, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -5853,6 +5855,11 @@ duplexer@^0.1.2: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + easymde@^2.10.1, easymde@^2.15.0: version "2.18.0" resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.18.0.tgz#ff1397d07329b1a7b9187d2d0c20766fa16b3b1b" @@ -5864,14 +5871,6 @@ easymde@^2.10.1, easymde@^2.15.0: codemirror-spell-checker "1.1.2" marked "^4.1.0" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - ed2curve@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/ed2curve/-/ed2curve-0.3.0.tgz#322b575152a45305429d546b071823a93129a05d" @@ -5963,13 +5962,6 @@ enhanced-resolve@^5.7.0: graceful-fs "^4.2.4" tapable "^2.2.0" -enquirer@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -6134,6 +6126,34 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3: d "^1.0.1" ext "^1.1.2" +esbuild@^0.17.6: + version "0.17.19" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" + integrity sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw== + optionalDependencies: + "@esbuild/android-arm" "0.17.19" + "@esbuild/android-arm64" "0.17.19" + "@esbuild/android-x64" "0.17.19" + "@esbuild/darwin-arm64" "0.17.19" + "@esbuild/darwin-x64" "0.17.19" + "@esbuild/freebsd-arm64" "0.17.19" + "@esbuild/freebsd-x64" "0.17.19" + "@esbuild/linux-arm" "0.17.19" + "@esbuild/linux-arm64" "0.17.19" + "@esbuild/linux-ia32" "0.17.19" + "@esbuild/linux-loong64" "0.17.19" + "@esbuild/linux-mips64el" "0.17.19" + "@esbuild/linux-ppc64" "0.17.19" + "@esbuild/linux-riscv64" "0.17.19" + "@esbuild/linux-s390x" "0.17.19" + "@esbuild/linux-x64" "0.17.19" + "@esbuild/netbsd-x64" "0.17.19" + "@esbuild/openbsd-x64" "0.17.19" + "@esbuild/sunos-x64" "0.17.19" + "@esbuild/win32-arm64" "0.17.19" + "@esbuild/win32-ia32" "0.17.19" + "@esbuild/win32-x64" "0.17.19" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -6348,11 +6368,6 @@ etag@1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eventemitter2@6.4.7: - version "6.4.7" - resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" - integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== - eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" @@ -6381,7 +6396,20 @@ exec-sh@^0.3.2: resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== -execa@4.1.0, execa@^4.0.0: +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== @@ -6396,19 +6424,6 @@ execa@4.1.0, execa@^4.0.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -6424,13 +6439,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -executable@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" - integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== - dependencies: - pify "^2.2.0" - exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -6483,7 +6491,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.2: +extend@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -6512,27 +6520,6 @@ extract-stack@^2.0.0: resolved "https://registry.yarnpkg.com/extract-stack/-/extract-stack-2.0.0.tgz#11367bc865bfcd9bc0db3123e5edb57786f11f9b" integrity sha512-AEo4zm+TenK7zQorGK1f9mJ8L14hnTDi2ZQPR+Mub1NX8zimka1mXpV5LpH8x9HoUmFSHZCfLHqWvp0Y4FxxzQ== -extract-zip@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" - integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg== - dependencies: - debug "^4.1.1" - get-stream "^5.1.0" - yauzl "^2.10.0" - optionalDependencies: - "@types/yauzl" "^2.9.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@3.1.3, fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -6610,13 +6597,6 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g== - dependencies: - pend "~1.2.0" - fecha@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" @@ -6650,13 +6630,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -6764,10 +6737,13 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" form-data@^3.0.0: version "3.0.1" @@ -6778,15 +6754,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - formdata-polyfill@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" @@ -6918,7 +6885,7 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-stream@^5.0.0, get-stream@^5.1.0: +get-stream@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -6943,20 +6910,6 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== -getos@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" - integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q== - dependencies: - async "^3.2.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - git-parse@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/git-parse/-/git-parse-2.1.1.tgz#01cf88d17a6adbe1173246f4497849fc5842381b" @@ -7025,6 +6978,17 @@ glob@8.0.1: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.3.10: + version "10.3.10" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" + integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.5" + minimatch "^9.0.1" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-scurry "^1.10.1" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -7072,13 +7036,6 @@ global-agent@3.0.0: semver "^7.3.2" serialize-error "^7.0.1" -global-dirs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" - integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== - dependencies: - ini "2.0.0" - globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -7098,7 +7055,7 @@ globalthis@^1.0.1, globalthis@^1.0.3: dependencies: define-properties "^1.1.3" -globby@^11.0.1, globby@^11.1.0: +globby@^11.0.1, globby@^11.0.3, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -7178,6 +7135,11 @@ graphql-tag@2.12.6, graphql-tag@^2.10.1, graphql-tag@^2.11.0, graphql-tag@^2.12. dependencies: tslib "^2.1.0" +graphql-ws@^5.14.3: + version "5.14.3" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.14.3.tgz#fb1fba011a0ae9c4e86d831cae2ec27955168b9a" + integrity sha512-F/i2xNIVbaEF2xWggID0X/UZQa2V8kqKDPO8hwmu53bVOcTL7uNkxnexeEgSCVxYBQUTUNEI8+e4LO1FOhKPKQ== + "graphql@14.0.2 - 14.2.0 || ^14.3.1 || ^15.0.0", graphql@^15.5.0: version "15.8.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" @@ -7455,15 +7417,6 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-signature@~1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9" - integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw== - dependencies: - assert-plus "^1.0.0" - jsprim "^2.0.2" - sshpk "^1.14.1" - https-browserify@1.0.0, https-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" @@ -7516,7 +7469,7 @@ iconv-lite@^0.6.2: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: +ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -7607,11 +7560,6 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -ini@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" - integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== - inline-style-parser@0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" @@ -7857,13 +7805,6 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-ci@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867" - integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ== - dependencies: - ci-info "^3.2.0" - is-core-module@^2.11.0, is-core-module@^2.9.0: version "2.12.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4" @@ -7983,14 +7924,6 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== -is-installed-globally@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" - integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ== - dependencies: - global-dirs "^3.0.0" - is-path-inside "^3.0.2" - is-ip@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" @@ -8042,7 +7975,7 @@ is-observable@^1.1.0: dependencies: symbol-observable "^1.1.0" -is-path-inside@^3.0.2, is-path-inside@^3.0.3: +is-path-inside@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -8141,16 +8074,11 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: gopd "^1.0.1" has-tostringtag "^1.0.0" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== -is-unicode-supported@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" - integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== - is-weakmap@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" @@ -8225,10 +8153,10 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.0" @@ -8327,6 +8255,15 @@ it-to-stream@^1.0.0: p-fifo "^1.0.0" readable-stream "^3.6.0" +jackspeak@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.8.5" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46" @@ -8731,6 +8668,11 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" +joycon@^3.0.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + js-cookie@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" @@ -8756,11 +8698,6 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - jsdom@^16.4.0: version "16.7.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" @@ -8819,11 +8756,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -8836,7 +8768,7 @@ json-stable-stringify@^1.0.2: dependencies: jsonify "^0.0.1" -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -8888,16 +8820,6 @@ jsonify@^0.0.1: resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== -jsprim@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d" - integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" @@ -8952,11 +8874,6 @@ language-tags@=1.0.5: dependencies: language-subtag-registry "~0.3.2" -lazy-ass@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" - integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== - lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -8990,6 +8907,11 @@ lie@3.1.1: dependencies: immediate "~3.0.5" +lilconfig@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52" + integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -9036,20 +8958,6 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" -listr2@^3.8.3: - version "3.14.0" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" - integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g== - dependencies: - cli-truncate "^2.1.0" - colorette "^2.0.16" - log-update "^4.0.0" - p-map "^4.0.0" - rfdc "^1.3.0" - rxjs "^7.5.1" - through "^2.3.8" - wrap-ansi "^7.0.0" - listr@0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -9091,6 +8999,11 @@ load-script@^1.0.0: resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" integrity sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA== +load-tsconfig@^0.2.3: + version "0.2.5" + resolved "https://registry.yarnpkg.com/load-tsconfig/-/load-tsconfig-0.2.5.tgz#453b8cd8961bfb912dea77eb6c168fe8cca3d3a1" + integrity sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg== + loader-utils@1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" @@ -9191,11 +9104,6 @@ lodash.merge@^4.6.1, lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.once@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - lodash.partition@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.partition/-/lodash.partition-4.6.0.tgz#a38e46b73469e0420b0da1212e66d414be364ba4" @@ -9238,14 +9146,6 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-symbols@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - log-update@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" @@ -9255,16 +9155,6 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" -log-update@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" - integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== - dependencies: - ansi-escapes "^4.3.0" - cli-cursor "^3.1.0" - slice-ansi "^4.0.0" - wrap-ansi "^6.2.0" - loglevel-plugin-prefix@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz#2fe0e05f1a820317d98d8c123e634c1bd84ff644" @@ -9323,6 +9213,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +"lru-cache@^9.1.1 || ^10.0.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" + integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + lz-string@^1.4.4: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -9648,7 +9543,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19: +mime-types@^2.1.12, mime-types@^2.1.27: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -9702,6 +9597,13 @@ minimatch@^5.0.0, minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@~3.0.2: version "3.0.8" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.8.tgz#5e6a59bd11e2ab0de1cfb843eb2d82e546c321c1" @@ -9714,6 +9616,11 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.7: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -9807,6 +9714,15 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + nano-css@^5.3.0, nano-css@^5.3.1: version "5.3.5" resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.3.5.tgz#3075ea29ffdeb0c7cb6d25edb21d8f7fa8e8fe8e" @@ -10201,7 +10117,7 @@ nzh@^1.0.4: resolved "https://registry.yarnpkg.com/nzh/-/nzh-1.0.8.tgz#aa43e38720fa7a625630b65eb20863da3c7d62f9" integrity sha512-fm9qlo0aBJxbi3dt4ix+iqRa95tAWAptwmSNTfUEleCitbTz8D3i7KPu0O2mecnvVn+b/JMb4uJqHOj2yJf3hQ== -object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -10394,11 +10310,6 @@ os-browserify@0.3.0, os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== -ospath@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" - integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA== - p-defer@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-3.0.0.tgz#d1dceb4ee9b2b604b1d94ffec83760175d4e6f83" @@ -10460,13 +10371,6 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" - integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== - dependencies: - aggregate-error "^3.0.0" - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -10649,6 +10553,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" + integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== + dependencies: + lru-cache "^9.1.1 || ^10.0.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.2.0.tgz#fa7877ecbc495c601907562222453c43cc204a5f" @@ -10682,16 +10594,6 @@ pdfast@^0.2.0: resolved "https://registry.yarnpkg.com/pdfast/-/pdfast-0.2.0.tgz#8cbc556e1bf2522177787c0de2e0d4373ba885c9" integrity sha512-cq6TTu6qKSFUHwEahi68k/kqN2mfepjkGrG9Un70cgdRRKLKY6Rf8P8uvP2NvZktaQZNF3YE7agEkLj0vGK9bA== -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -10707,11 +10609,6 @@ pidtree@^0.3.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a" integrity sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA== -pify@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -10760,6 +10657,14 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== +postcss-load-config@^3.0.1: + version "3.1.4" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855" + integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg== + dependencies: + lilconfig "^2.0.5" + yaml "^1.10.2" + postcss@8.2.15: version "8.2.15" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65" @@ -10805,11 +10710,6 @@ prettier@^2.7.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450" integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw== -pretty-bytes@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" - integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== - pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" @@ -11077,12 +10977,7 @@ protocols@^2.0.1: resolved "https://registry.yarnpkg.com/protocols/-/protocols-2.0.1.tgz#8f155da3fc0f32644e83c5782c8e8212ccf70a86" integrity sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q== -proxy-from-env@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== - -psl@^1.1.28, psl@^1.1.33: +psl@^1.1.33: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== @@ -11141,13 +11036,6 @@ qs@^6.9.4: dependencies: side-channel "^1.0.4" -qs@~6.10.3: - version "6.10.5" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4" - integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ== - dependencies: - side-channel "^1.0.4" - query-string@*: version "8.1.0" resolved "https://registry.yarnpkg.com/query-string/-/query-string-8.1.0.tgz#e7f95367737219544cd360a11a4f4ca03836e115" @@ -11705,10 +11593,10 @@ react-hook-form@~5.6.0: resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-5.6.3.tgz#fb807450730daab8020d18cf7106754baa33e7d3" integrity sha512-qqcoDM5UD69aUMQejhx90XM4gXUAlVRH3mDRa9TDZINK6FAM7EjReJKjiIZzU9mShjjKTQl3RpiHKaKzZqI7RA== -react-icons@^4.4.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.8.0.tgz#621e900caa23b912f737e41be57f27f6b2bff445" - integrity sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg== +react-icons@^4.12.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.12.0.tgz#54806159a966961bfd5cdb26e492f4dafd6a8d78" + integrity sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw== react-infinite-scroll-component@^6.1.0: version "6.1.0" @@ -12082,13 +11970,6 @@ repeat-string@^1.0.0, repeat-string@^1.5.2, repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -request-progress@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe" - integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg== - dependencies: - throttleit "^1.0.0" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -12172,14 +12053,6 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" @@ -12202,11 +12075,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -12250,6 +12118,13 @@ rollup@^0.25.8: minimist "^1.2.0" source-map-support "^0.3.2" +rollup@^3.2.5: + version "3.29.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981" + integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw== + optionalDependencies: + fsevents "~2.3.2" + rope-sequence@^1.3.0: version "1.3.3" resolved "https://registry.yarnpkg.com/rope-sequence/-/rope-sequence-1.3.3.tgz#3f67fc106288b84b71532b4a5fd9d4881e4457f0" @@ -12286,7 +12161,7 @@ rxjs@^6.3.3: dependencies: tslib "^1.9.0" -rxjs@^7.5.1, rxjs@^7.8.0: +rxjs@^7.8.0: version "7.8.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4" integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg== @@ -12319,7 +12194,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -12549,6 +12424,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + simple-statistics@~6.1.0: version "6.1.1" resolved "https://registry.yarnpkg.com/simple-statistics/-/simple-statistics-6.1.1.tgz#e3a0799ffc49914d6f421c5a4ac585f6a13e2bad" @@ -12588,15 +12468,6 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== -slice-ansi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" - integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -12805,21 +12676,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -sshpk@^1.14.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - stack-generator@^2.0.5: version "2.0.10" resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" @@ -12967,6 +12823,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + name string-width-cjs + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -12984,14 +12850,14 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" string.prototype.matchall@^4.0.8: version "4.0.8" @@ -13066,6 +12932,14 @@ stringify-entities@^3.0.1: character-entities-legacy "^1.0.0" xtend "^4.0.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: + name strip-ansi-cjs + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -13073,13 +12947,6 @@ strip-ansi@6.0.0: dependencies: ansi-regex "^5.0.0" -strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -13094,6 +12961,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -13160,6 +13034,19 @@ stylis@^4.0.6: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== +sucrase@^3.20.3: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -13282,6 +13169,20 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + throat@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" @@ -13297,12 +13198,7 @@ throttle-debounce@^3.0.1: resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-3.0.1.tgz#32f94d84dfa894f786c9a1f290e7a645b6a19abb" integrity sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg== -throttleit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" - integrity sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g== - -through@^2.3.8, through@~2.3.4, through@~2.3.8: +through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -13333,13 +13229,6 @@ tippy.js@^6.3.7: dependencies: "@popperjs/core" "^2.9.0" -tmp@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" - integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== - dependencies: - rimraf "^3.0.0" - tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -13424,14 +13313,6 @@ tough-cookie@^4.0.0: universalify "^0.2.0" url-parse "^1.5.3" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -13451,6 +13332,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trough@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" @@ -13461,6 +13347,11 @@ ts-easing@^0.2.0: resolved "https://registry.yarnpkg.com/ts-easing/-/ts-easing-0.2.0.tgz#c8a8a35025105566588d87dbda05dd7fbfa5a4ec" integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ== +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + ts-invariant@^0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c" @@ -13526,6 +13417,26 @@ tslib@^2, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +tsup@^6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/tsup/-/tsup-6.7.0.tgz#416f350f32a07b6ae86792ad7e52b0cafc566d64" + integrity sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ== + dependencies: + bundle-require "^4.0.0" + cac "^6.7.12" + chokidar "^3.5.1" + debug "^4.3.1" + esbuild "^0.17.6" + execa "^5.0.0" + globby "^11.0.3" + joycon "^3.0.1" + postcss-load-config "^3.0.1" + resolve-from "^5.0.0" + rollup "^3.2.5" + source-map "0.8.0-beta.0" + sucrase "^3.20.3" + tree-kill "^1.2.2" + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -13560,10 +13471,10 @@ tweetnacl@1.x.x, tweetnacl@^1.0.3: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== +twitter-api-v2@^1.15.0: + version "1.15.2" + resolved "https://registry.yarnpkg.com/twitter-api-v2/-/twitter-api-v2-1.15.2.tgz#212944065e86c1a8001f712447f06e275514faea" + integrity sha512-iIGItwkUGsAGA6VNnULXL5dllVJ35IZQjLSTWvqSn4M7s19B6X1+pUB/ZDSJD+u6q6+FinNxy0dnDIEoCZ5x8w== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" @@ -13796,11 +13707,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -untildify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" - integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== - update-browserslist-db@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" @@ -13942,7 +13848,7 @@ uuid@^7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@^8.3.0, uuid@^8.3.2: +uuid@^8.3.0: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -13978,15 +13884,6 @@ venn.js@~0.2.20: d3-transition "^1.0.1" fmin "0.0.2" -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vfile-message@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" @@ -14262,6 +14159,16 @@ wordwrap@0.0.2: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" integrity sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: + name wrap-ansi-cjs + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" @@ -14279,14 +14186,14 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" wrappy@1: version "1.0.2" @@ -14348,7 +14255,7 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0: +yaml@^1.10.0, yaml@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== @@ -14393,14 +14300,6 @@ yarn@^1.22.17: resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.19.tgz#4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== -yauzl@^2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -14453,6 +14352,11 @@ zen-observable@0.8.15, zen-observable@^0.8.0: resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== +zod@^3.22.4: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"