Refactor animations (#2261)
* Fix fireworks not checking localStorage flag * Refactor animations * Don't import unused animations * Remove unused hook --------- Co-authored-by: k00b <k00b@stacker.news>
This commit is contained in:
parent
3a27057781
commit
18a38d8363
@ -7,7 +7,7 @@ import {
|
||||
setRangeValue,
|
||||
stringToRgb
|
||||
} from 'tsparticles-engine'
|
||||
import useDarkMode from './dark-mode'
|
||||
import useDarkMode from '@/components/dark-mode'
|
||||
|
||||
export const FireworksContext = createContext({
|
||||
strike: () => {}
|
72
components/animation/index.js
Normal file
72
components/animation/index.js
Normal file
@ -0,0 +1,72 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useMe } from '@/components/me'
|
||||
import { randInRange } from '@/lib/rand'
|
||||
|
||||
// import { LightningProvider, useLightning } from './lightning'
|
||||
import { FireworksProvider, useFireworks } from './fireworks'
|
||||
// import { SnowProvider, useSnow } from './snow'
|
||||
|
||||
const [SelectedAnimationProvider, useSelectedAnimation] = [
|
||||
// LightningProvider, useLightning
|
||||
FireworksProvider, useFireworks
|
||||
// SnowProvider, useSnow // TODO: the snow animation doesn't seem to work anymore
|
||||
]
|
||||
|
||||
export function AnimationProvider ({ children }) {
|
||||
return (
|
||||
<SelectedAnimationProvider>
|
||||
<AnimationHooks>
|
||||
{children}
|
||||
</AnimationHooks>
|
||||
</SelectedAnimationProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useAnimation () {
|
||||
const animate = useSelectedAnimation()
|
||||
|
||||
return useCallback(() => {
|
||||
const should = window.localStorage.getItem('lnAnimate') || 'yes'
|
||||
if (should !== 'yes') return false
|
||||
animate()
|
||||
return true
|
||||
}, [animate])
|
||||
}
|
||||
|
||||
export function useAnimationEnabled () {
|
||||
const [enabled, setEnabled] = useState(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
const enabled = window.localStorage.getItem('lnAnimate') || 'yes'
|
||||
setEnabled(enabled === 'yes')
|
||||
}, [])
|
||||
|
||||
const toggleEnabled = useCallback(() => {
|
||||
setEnabled(enabled => {
|
||||
const newEnabled = !enabled
|
||||
window.localStorage.setItem('lnAnimate', newEnabled ? 'yes' : 'no')
|
||||
return newEnabled
|
||||
})
|
||||
}, [])
|
||||
|
||||
return [enabled, toggleEnabled]
|
||||
}
|
||||
|
||||
function AnimationHooks ({ children }) {
|
||||
const { me } = useMe()
|
||||
const animate = useAnimation()
|
||||
|
||||
useEffect(() => {
|
||||
if (me || window.localStorage.getItem('striked') || window.localStorage.getItem('lnAnimated')) return
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
const animated = animate()
|
||||
if (animated) {
|
||||
window.localStorage.setItem('lnAnimated', 'yep')
|
||||
}
|
||||
}, randInRange(3000, 10000))
|
||||
return () => clearTimeout(timeout)
|
||||
}, [me?.id, animate])
|
||||
|
||||
return children
|
||||
}
|
@ -13,16 +13,11 @@ export class LightningProvider extends React.Component {
|
||||
* @returns boolean indicating whether the strike actually happened, based on user preferences
|
||||
*/
|
||||
strike = () => {
|
||||
const should = window.localStorage.getItem('lnAnimate') || 'yes'
|
||||
if (should === 'yes') {
|
||||
this.setState(state => {
|
||||
return {
|
||||
bolts: [...state.bolts, <Lightning key={state.bolts.length} onDone={() => this.unstrike(state.bolts.length)} />]
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
this.setState(state => {
|
||||
return {
|
||||
bolts: [...state.bolts, <Lightning key={state.bolts.length} onDone={() => this.unstrike(state.bolts.length)} />]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
unstrike = (index) => {
|
@ -11,21 +11,16 @@ export const SnowProvider = ({ children }) => {
|
||||
const [flakes, setFlakes] = useState(Array(1024))
|
||||
|
||||
const snow = useCallback(() => {
|
||||
const should = window.localStorage.getItem('lnAnimate') || 'yes'
|
||||
if (should === 'yes') {
|
||||
// amount of flakes to add
|
||||
const n = Math.floor(randInRange(5, 30))
|
||||
const newFlakes = [...flakes]
|
||||
let i
|
||||
for (i = startIndex; i < (startIndex + n); ++i) {
|
||||
const key = startIndex + i
|
||||
newFlakes[i % MAX_FLAKES] = <Snow key={key} />
|
||||
}
|
||||
setStartIndex(i % MAX_FLAKES)
|
||||
setFlakes(newFlakes)
|
||||
return true
|
||||
// amount of flakes to add
|
||||
const n = Math.floor(randInRange(5, 30))
|
||||
const newFlakes = [...flakes]
|
||||
let i
|
||||
for (i = startIndex; i < (startIndex + n); ++i) {
|
||||
const key = startIndex + i
|
||||
newFlakes[i % MAX_FLAKES] = <Snow key={key} />
|
||||
}
|
||||
return false
|
||||
setStartIndex(i % MAX_FLAKES)
|
||||
setFlakes(newFlakes)
|
||||
}, [setFlakes, startIndex])
|
||||
|
||||
return (
|
@ -12,10 +12,10 @@ import No from '@/svgs/no.svg'
|
||||
import Bolt from '@/svgs/bolt.svg'
|
||||
import Amboss from '@/svgs/amboss.svg'
|
||||
import Mempool from '@/svgs/bimi.svg'
|
||||
import { useEffect, useState } from 'react'
|
||||
import Rewards from './footer-rewards'
|
||||
import useDarkMode from './dark-mode'
|
||||
import ActionTooltip from './action-tooltip'
|
||||
import { useAnimationEnabled } from '@/components/animation'
|
||||
|
||||
const RssPopover = (
|
||||
<Popover>
|
||||
@ -145,24 +145,10 @@ const LegalPopover = (
|
||||
export default function Footer ({ links = true }) {
|
||||
const [darkMode, darkModeToggle] = useDarkMode()
|
||||
|
||||
const [lightning, setLightning] = useState(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
setLightning(window.localStorage.getItem('lnAnimate') || 'yes')
|
||||
}, [])
|
||||
|
||||
const toggleLightning = () => {
|
||||
if (lightning === 'yes') {
|
||||
window.localStorage.setItem('lnAnimate', 'no')
|
||||
setLightning('no')
|
||||
} else {
|
||||
window.localStorage.setItem('lnAnimate', 'yes')
|
||||
setLightning('yes')
|
||||
}
|
||||
}
|
||||
const [animationEnabled, toggleAnimation] = useAnimationEnabled()
|
||||
|
||||
const DarkModeIcon = darkMode ? Sun : Moon
|
||||
const LnIcon = lightning === 'yes' ? No : Bolt
|
||||
const LnIcon = animationEnabled ? No : Bolt
|
||||
|
||||
const version = process.env.NEXT_PUBLIC_COMMIT_HASH
|
||||
|
||||
@ -175,8 +161,8 @@ export default function Footer ({ links = true }) {
|
||||
<ActionTooltip notForm overlayText={`${darkMode ? 'disable' : 'enable'} dark mode`}>
|
||||
<DarkModeIcon onClick={darkModeToggle} width={20} height={20} className='fill-grey theme' suppressHydrationWarning />
|
||||
</ActionTooltip>
|
||||
<ActionTooltip notForm overlayText={`${lightning === 'yes' ? 'disable' : 'enable'} lightning animations`}>
|
||||
<LnIcon onClick={toggleLightning} width={20} height={20} className='ms-2 fill-grey theme' suppressHydrationWarning />
|
||||
<ActionTooltip notForm overlayText={`${animationEnabled ? 'disable' : 'enable'} lightning animations`}>
|
||||
<LnIcon onClick={toggleAnimation} width={20} height={20} className='ms-2 fill-grey theme' suppressHydrationWarning />
|
||||
</ActionTooltip>
|
||||
</div>
|
||||
<div className='mb-0' style={{ fontWeight: 500 }}>
|
||||
|
@ -13,7 +13,7 @@ import { ACT_MUTATION } from '@/fragments/paidAction'
|
||||
import { meAnonSats } from '@/lib/apollo'
|
||||
import { BoostItemInput } from './adv-post-form'
|
||||
import { useSendWallets } from '@/wallets/index'
|
||||
import { useFireworks } from './fireworks'
|
||||
import { useAnimation } from '@/components/animation'
|
||||
|
||||
const defaultTips = [100, 1000, 10_000, 100_000]
|
||||
|
||||
@ -96,7 +96,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
|
||||
}, [onClose, item.id])
|
||||
|
||||
const actor = useAct()
|
||||
const strike = useFireworks()
|
||||
const animate = useAnimation()
|
||||
|
||||
const onSubmit = useCallback(async ({ amount }) => {
|
||||
if (abortSignal && zapUndoTrigger({ me, amount })) {
|
||||
@ -111,7 +111,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
|
||||
}
|
||||
|
||||
const onPaid = () => {
|
||||
strike()
|
||||
animate()
|
||||
onClose?.()
|
||||
if (!me) setItemMeAnonSats({ id: item.id, amount })
|
||||
}
|
||||
@ -143,7 +143,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
|
||||
})
|
||||
if (error) throw error
|
||||
addCustomTip(Number(amount))
|
||||
}, [me, actor, wallets.length, act, item.id, onClose, abortSignal, strike])
|
||||
}, [me, actor, wallets.length, act, item.id, onClose, abortSignal, animate])
|
||||
|
||||
return act === 'BOOST'
|
||||
? <BoostForm step={step} onSubmit={onSubmit} item={item} inputRef={inputRef} act={act}>{children}</BoostForm>
|
||||
@ -300,7 +300,7 @@ export function useAct ({ query = ACT_MUTATION, ...options } = {}) {
|
||||
export function useZap () {
|
||||
const wallets = useSendWallets()
|
||||
const act = useAct()
|
||||
const strike = useFireworks()
|
||||
const animate = useAnimation()
|
||||
const toaster = useToast()
|
||||
|
||||
return useCallback(async ({ item, me, abortSignal }) => {
|
||||
@ -314,7 +314,7 @@ export function useZap () {
|
||||
|
||||
try {
|
||||
await abortSignal.pause({ me, amount: sats })
|
||||
strike()
|
||||
animate()
|
||||
// batch zaps if wallet is enabled or using fee credits so they can be executed serially in a single request
|
||||
const { error } = await act({ variables, optimisticResponse, context: { batch: wallets.length > 0 || me?.privates?.sats > sats } })
|
||||
if (error) throw error
|
||||
@ -327,7 +327,7 @@ export function useZap () {
|
||||
// but right now this toast is noisy for optimistic zaps
|
||||
console.error(error)
|
||||
}
|
||||
}, [act, toaster, strike, wallets])
|
||||
}, [act, toaster, animate, wallets])
|
||||
}
|
||||
|
||||
export class ActCanceledError extends Error {
|
||||
|
@ -14,8 +14,6 @@ import { abbrNum } from '../../lib/format'
|
||||
import { useServiceWorker } from '../serviceworker'
|
||||
import { signOut } from 'next-auth/react'
|
||||
import Badges from '../badge'
|
||||
import { randInRange } from '../../lib/rand'
|
||||
import { useFireworks } from '../fireworks'
|
||||
import LightningIcon from '../../svgs/bolt.svg'
|
||||
import SearchIcon from '../../svgs/search-line.svg'
|
||||
import classNames from 'classnames'
|
||||
@ -400,20 +398,6 @@ export function LoginButtons ({ handleClose }) {
|
||||
}
|
||||
|
||||
export function AnonDropdown ({ path }) {
|
||||
const strike = useFireworks()
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.localStorage.getItem('striked')) {
|
||||
const to = setTimeout(() => {
|
||||
const striked = strike()
|
||||
if (striked) {
|
||||
window.localStorage.setItem('striked', 'yep')
|
||||
}
|
||||
}, randInRange(3000, 10000))
|
||||
return () => clearTimeout(to)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='position-relative'>
|
||||
<Dropdown className={styles.dropdown} align='end' autoClose>
|
||||
|
@ -6,7 +6,7 @@ import { numWithUnits } from '@/lib/format'
|
||||
import { useShowModal } from './modal'
|
||||
import { useRoot } from './root'
|
||||
import { ActCanceledError, useAct } from './item-act'
|
||||
import { useFireworks } from './fireworks'
|
||||
import { useAnimation } from '@/components/animation'
|
||||
import { useToast } from './toast'
|
||||
import { useSendWallets } from '@/wallets/index'
|
||||
import { Form, SubmitButton } from './form'
|
||||
@ -48,7 +48,7 @@ export default function PayBounty ({ children, item }) {
|
||||
const { me } = useMe()
|
||||
const showModal = useShowModal()
|
||||
const root = useRoot()
|
||||
const strike = useFireworks()
|
||||
const animate = useAnimation()
|
||||
const toaster = useToast()
|
||||
const wallets = useSendWallets()
|
||||
|
||||
@ -61,7 +61,7 @@ export default function PayBounty ({ children, item }) {
|
||||
|
||||
const handlePayBounty = async onCompleted => {
|
||||
try {
|
||||
strike()
|
||||
animate()
|
||||
const { error } = await act({ onCompleted })
|
||||
if (error) throw error
|
||||
} catch (error) {
|
||||
|
@ -10,7 +10,7 @@ import { useRouter } from 'next/dist/client/router'
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { ShowModalProvider } from '@/components/modal'
|
||||
import ErrorBoundary from '@/components/error-boundary'
|
||||
import { FireworksProvider } from '@/components/fireworks'
|
||||
import { AnimationProvider } from '@/components/animation'
|
||||
import { ToastProvider } from '@/components/toast'
|
||||
import { ServiceWorkerProvider } from '@/components/serviceworker'
|
||||
import { SSR } from '@/lib/constants'
|
||||
@ -116,7 +116,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
|
||||
<WebLnProvider>
|
||||
<ServiceWorkerProvider>
|
||||
<PriceProvider price={price}>
|
||||
<FireworksProvider>
|
||||
<AnimationProvider>
|
||||
<ToastProvider>
|
||||
<ShowModalProvider>
|
||||
<BlockHeightProvider blockHeight={blockHeight}>
|
||||
@ -129,7 +129,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
|
||||
</BlockHeightProvider>
|
||||
</ShowModalProvider>
|
||||
</ToastProvider>
|
||||
</FireworksProvider>
|
||||
</AnimationProvider>
|
||||
</PriceProvider>
|
||||
</ServiceWorkerProvider>
|
||||
</WebLnProvider>
|
||||
|
@ -2,7 +2,7 @@ import { getGetServerSideProps } from '@/api/ssrApollo'
|
||||
import CCInfo from '@/components/info/cc'
|
||||
import { Form, Input, SubmitButton } from '@/components/form'
|
||||
import { CenterLayout } from '@/components/layout'
|
||||
import { useFireworks } from '@/components/fireworks'
|
||||
import { useAnimation } from '@/components/animation'
|
||||
import { useMe } from '@/components/me'
|
||||
import { useShowModal } from '@/components/modal'
|
||||
import { usePaidMutation } from '@/components/use-paid-mutation'
|
||||
@ -76,7 +76,7 @@ function WithdrawButton ({ className }) {
|
||||
|
||||
export function BuyCreditsButton ({ className }) {
|
||||
const showModal = useShowModal()
|
||||
const strike = useFireworks()
|
||||
const animate = useAnimation()
|
||||
const [buyCredits] = usePaidMutation(BUY_CREDITS)
|
||||
|
||||
return (
|
||||
@ -94,7 +94,7 @@ export function BuyCreditsButton ({ className }) {
|
||||
credits: Number(amount)
|
||||
},
|
||||
onCompleted: () => {
|
||||
strike()
|
||||
animate()
|
||||
}
|
||||
})
|
||||
onClose()
|
||||
|
@ -13,7 +13,7 @@ import { useShowModal } from '@/components/modal'
|
||||
import dynamic from 'next/dynamic'
|
||||
import { FAST_POLL_INTERVAL, SSR } from '@/lib/constants'
|
||||
import { useToast } from '@/components/toast'
|
||||
import { useFireworks } from '@/components/fireworks'
|
||||
import { useAnimation } from '@/components/animation'
|
||||
import { Col, Row } from 'react-bootstrap'
|
||||
import { useData } from '@/components/use-data'
|
||||
import { GrowthPieChartSkeleton } from '@/components/charts-skeletons'
|
||||
@ -133,7 +133,7 @@ export default function Rewards ({ ssrData }) {
|
||||
export function DonateButton () {
|
||||
const showModal = useShowModal()
|
||||
const toaster = useToast()
|
||||
const strike = useFireworks()
|
||||
const animate = useAnimation()
|
||||
const [donateToRewards] = usePaidMutation(DONATE)
|
||||
|
||||
return (
|
||||
@ -151,7 +151,7 @@ export function DonateButton () {
|
||||
sats: Number(amount)
|
||||
},
|
||||
onCompleted: () => {
|
||||
strike()
|
||||
animate()
|
||||
toaster.success('donated')
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user