Skip to content

Commit

Permalink
Merge pull request #677 from dappforce/deploy/epic
Browse files Browse the repository at this point in the history
  • Loading branch information
samchuk-vlad authored Jun 14, 2024
2 parents 887b780 + d7e351f commit 8f84a8d
Show file tree
Hide file tree
Showing 23 changed files with 14,366 additions and 94 deletions.
13,394 changes: 13,394 additions & 0 deletions src/assets/animations/cat-clicker.json

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions src/components/CatClicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import CatClickerAnimation from '@/assets/animations/cat-clicker.json'
import Lottie, { LottieProps } from 'react-lottie'

export type HamsterLoadingProps = Omit<LottieProps, 'options'>

export default function CatClicker({ ...props }: HamsterLoadingProps) {
const defaultOptions: LottieProps = {
...props,
options: {
loop: true,
autoplay: true,
animationData: CatClickerAnimation,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
},
}

return <Lottie {...defaultOptions} isClickToPauseDisabled={true} />
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import NewCommunityModal from '@/components/community/NewCommunityModal'
import useGetTheme from '@/hooks/useGetTheme'
import { useConfigContext } from '@/providers/config/ConfigProvider'
import { getLinkedTelegramAccountsQuery } from '@/services/api/notifications/query'
import { getBalanceQuery } from '@/services/datahub/balances/query'
import { getBalanceQuery } from '@/services/datahub/leaderboard/points-balance/query'
import { getProfileQuery } from '@/services/datahub/profiles/query'
import { useSendEvent } from '@/stores/analytics'
import { useMyMainAddress } from '@/stores/my-account'
Expand Down
2 changes: 1 addition & 1 deletion src/modules/chat/HomePage/MissingRewards.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Button from '@/components/Button'
import useLinkedEvmAddress from '@/hooks/useLinkedEvmAddress'
import { getBalanceQuery } from '@/services/datahub/balances/query'
import { getBalanceQuery } from '@/services/datahub/leaderboard/points-balance/query'
import { useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { IoWarning } from 'react-icons/io5'
Expand Down
24 changes: 18 additions & 6 deletions src/modules/points/PointsWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import Card from '@/components/Card'
import LinkText from '@/components/LinkText'
import { Skeleton } from '@/components/SkeletonFallback'
import useIsMounted from '@/hooks/useIsMounted'
import { getBalanceQuery } from '@/services/datahub/balances/query'
import { getTodaySuperLikeCountQuery } from '@/services/datahub/content-staking/query'
import { getBalanceQuery } from '@/services/datahub/leaderboard/points-balance/query'
import { useSendEvent } from '@/stores/analytics'
import { useMyAccount, useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
Expand All @@ -27,9 +27,13 @@ import { FaChevronDown } from 'react-icons/fa'
import { HiChevronRight, HiXMark } from 'react-icons/hi2'
import SlotCounter from 'react-slot-counter'

export default function PointsWidget(
props: ComponentProps<'div'> & { isNoTgScroll?: boolean }
) {
export default function PointsWidget({
withPointsAnimation = true,
...props
}: ComponentProps<'div'> & {
isNoTgScroll?: boolean
withPointsAnimation?: boolean
}) {
const [isOpen, setIsOpen] = useState(false)
const isMounted = useIsMounted()
const sendEvent = useSendEvent()
Expand Down Expand Up @@ -70,7 +74,7 @@ export default function PointsWidget(
<div className='flex items-center gap-2'>
<Image className='h-7 w-7' src={Diamond} alt='' />
<span className='flex items-center text-xl font-bold'>
<Points shorten />
<Points withPointsAnimation={withPointsAnimation} />
</span>
<FaChevronDown className='relative' />
</div>
Expand Down Expand Up @@ -292,7 +296,13 @@ function LikeCount({ shorten }: { shorten?: boolean }) {
return <span>{formatNumber(data?.count ?? '0', { shorten })}</span>
}

function Points({ shorten }: { shorten?: boolean }) {
function Points({
shorten,
withPointsAnimation = true,
}: {
shorten?: boolean
withPointsAnimation?: boolean
}) {
const isInitializedProxy = useMyAccount.use.isInitializedProxy()
const myAddress = useMyMainAddress()
const { data, isLoading } = getBalanceQuery.useQuery(myAddress || '')
Expand All @@ -306,6 +316,8 @@ function Points({ shorten }: { shorten?: boolean }) {
return <Skeleton className='inline-block w-12' />
}

if (!withPointsAnimation) return <span>{splitValues}</span>

return (
<SlotCounter
containerClassName='relative -top-0.5'
Expand Down
2 changes: 1 addition & 1 deletion src/modules/telegram/StatsPage/tmpData.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const myAddressIndex = 10001
const myAddressIndex = 50

const myAddressTmp = '0x3C66e2cE7B0d28415A0Ad1A0C4837E03ca407071'

Expand Down
159 changes: 130 additions & 29 deletions src/modules/telegram/TapPage/PointsClicker.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import WaiterImage from '@/assets/graphics/waiter.png'
import CatClicker from '@/components/CatClicker'
import {
decreaseEnergyValue,
increasePointsBalance,
} from '@/services/datahub/leaderboard/points-balance/optimistic'
import {
FULL_ENERGY_VALUE,
getClickedPointsByDayQuery,
getEnergyStateQuery,
} from '@/services/datahub/leaderboard/points-balance/query'
import { getActiveStakingTokenomicMetadataQuery } from '@/services/datahub/leaderboard/query'
import { useMyMainAddress } from '@/stores/my-account'
import { cx } from '@/utils/class-names'
import { useQueryClient } from '@tanstack/react-query'
import { useHapticFeedbackRaw } from '@tma.js/sdk-react'
import Image from 'next/image'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { TouchEvent, TouchList, useEffect, useRef, useState } from 'react'
import {
getEnergyStateStore,
getTappedPointsStateStore,
setEnergyStateToStore,
setTappedPointsStateToStore,
} from './store'

dayjs.extend(utc)

type PointsClickerProps = {
className?: string
Expand All @@ -13,6 +34,44 @@ const PointsClicker = ({ className }: PointsClickerProps) => {
const [isTouched, setIsTouched] = useState(false)
const [touches, setTouches] = useState<TouchList>()
const haptic = useHapticFeedbackRaw(true)
const client = useQueryClient()
const myAddress = useMyMainAddress()
const { data, isLoading: isEnergyLoading } = getEnergyStateQuery.useQuery(
myAddress || ''
)
const { data: tokenomicMetadata, isLoading: isTokenomicMetadataLoading } =
getActiveStakingTokenomicMetadataQuery.useQuery({})
const { data: clickedPointsByDay, isLoading: isClickedPointsLoading } =
getClickedPointsByDayQuery.useQuery(myAddress || '')

const [startAnimation, setStartAnimation] = useState(false)

const { energyValue } = data || {}

const isEmptyEnergy = energyValue === 0

const disableClicker =
isClickedPointsLoading ||
isTokenomicMetadataLoading ||
!tokenomicMetadata ||
isEnergyLoading ||
(clickedPointsByDay &&
clickedPointsByDay?.tapsCount >= tokenomicMetadata.maxTapsPerDay) ||
isEmptyEnergy

useEffect(() => {
let timeout: NodeJS.Timeout

if (startAnimation && !isTouched) {
timeout = setTimeout(() => {
setStartAnimation(false)
}, 1000)
}

return () => {
clearTimeout(timeout)
}
}, [startAnimation, isTouched])

useEffect(() => {
const refCurrent = ref.current
Expand All @@ -31,20 +90,24 @@ const PointsClicker = ({ className }: PointsClickerProps) => {
e.preventDefault()
}
}
refCurrent?.addEventListener('touchstart', onTouchStart, {

ref.current?.addEventListener('touchstart', onTouchStart, {
passive: false,
})
refCurrent?.addEventListener('touchmove', onTouchMove, {
passive: false,
})

return () => {
refCurrent?.removeEventListener('touchstart', onTouchStart)
refCurrent?.removeEventListener('touchmove', onTouchMove)
if (refCurrent) {
refCurrent.removeEventListener('touchstart', onTouchStart)
refCurrent.removeEventListener('touchmove', onTouchMove)
}
}
}, [])

const onMouseDown = (event: TouchEvent<HTMLDivElement>) => {
setStartAnimation(true)
setIsTouched(true)
setTouches(event.touches)
}
Expand All @@ -58,13 +121,51 @@ const PointsClicker = ({ className }: PointsClickerProps) => {
if (ref.current && touch) {
const word = document.createElement('div')
word.classList.add('floating-word')
word.textContent = 'Soon'
word.textContent = '+1'

word.style.left = touch.clientX - 110 + 'px'
word.style.top = touch.clientY - 130 + 'px'
const rect = ref.current.getBoundingClientRect()

const x = touch.clientX - rect.left
const y = touch.clientY - rect.top

word.style.left = x - 25 + 'px'
word.style.top = y - 25 + 'px'

ref.current.appendChild(word)

if (myAddress && !isEmptyEnergy) {
increasePointsBalance({
client,
address: myAddress,
pointsByClick: 1,
})

decreaseEnergyValue({
client,
address: myAddress,
energyValuePerClick: 1,
})
const storedTappedPoints = getTappedPointsStateStore()

const newTappedPoints = storedTappedPoints?.tappedPoints
? parseInt(storedTappedPoints.tappedPoints) + 1
: 1

setTappedPointsStateToStore({
tappedPoints: newTappedPoints.toString(),
})

const storedEnergy = getEnergyStateStore()

const newEnergyValue = storedEnergy?.energyValue
? parseInt(storedEnergy.energyValue) - 1
: FULL_ENERGY_VALUE - 1

setEnergyStateToStore({
energyValue: newEnergyValue.toString(),
timestamp: dayjs().utc().unix().toString(),
})
}
setTimeout(() => {
ref.current?.removeChild(word)
}, 3000)
Expand All @@ -77,28 +178,28 @@ const PointsClicker = ({ className }: PointsClickerProps) => {
}

return (
<div
ref={ref}
className={cx('relative max-h-[242px] max-w-[242px]', className)}
onTouchStart={onMouseDown}
onTouchEnd={onMouseUp}
>
<>
<div
className={cx(
'absolute z-0 h-[175px] w-[175px] bg-[#5E81EA] blur-[102px]',
'bottom-0 left-0 right-0 top-0 m-auto'
)}
style={{ transform: 'translate3d(0, 0, 0)' }}
></div>
<Image
src={WaiterImage}
alt=''
className={cx(
'h-fullw-full relative z-10',
isTouched && 'scale-95 transform'
)}
/>
</div>
ref={ref}
className={cx('relative pl-3', className)}
onTouchStart={disableClicker ? undefined : onMouseDown}
onTouchEnd={disableClicker ? undefined : onMouseUp}
>
<div
className={cx(
'absolute z-0 h-[175px] w-[175px] bg-[#5E81EA] blur-[102px]',
'bottom-0 left-0 right-0 top-0 m-auto'
)}
style={{ transform: 'translate3d(0, 0, 0)' }}
></div>
<CatClicker
isPaused={!startAnimation || disableClicker}
style={{
filter: disableClicker ? 'brightness(0.7) grayscale(0.8)' : '',
}}
/>
</div>
</>
)
}

Expand Down
Loading

0 comments on commit 8f84a8d

Please sign in to comment.