Skip to content

Commit 18a38d8

Browse files
ekzyishuumn
andauthored
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>
1 parent 3a27057 commit 18a38d8

File tree

12 files changed

+111
-79
lines changed

12 files changed

+111
-79
lines changed

components/fireworks.js renamed to components/animation/fireworks.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
setRangeValue,
88
stringToRgb
99
} from 'tsparticles-engine'
10-
import useDarkMode from './dark-mode'
10+
import useDarkMode from '@/components/dark-mode'
1111

1212
export const FireworksContext = createContext({
1313
strike: () => {}

components/animation/index.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { useCallback, useEffect, useState } from 'react'
2+
import { useMe } from '@/components/me'
3+
import { randInRange } from '@/lib/rand'
4+
5+
// import { LightningProvider, useLightning } from './lightning'
6+
import { FireworksProvider, useFireworks } from './fireworks'
7+
// import { SnowProvider, useSnow } from './snow'
8+
9+
const [SelectedAnimationProvider, useSelectedAnimation] = [
10+
// LightningProvider, useLightning
11+
FireworksProvider, useFireworks
12+
// SnowProvider, useSnow // TODO: the snow animation doesn't seem to work anymore
13+
]
14+
15+
export function AnimationProvider ({ children }) {
16+
return (
17+
<SelectedAnimationProvider>
18+
<AnimationHooks>
19+
{children}
20+
</AnimationHooks>
21+
</SelectedAnimationProvider>
22+
)
23+
}
24+
25+
export function useAnimation () {
26+
const animate = useSelectedAnimation()
27+
28+
return useCallback(() => {
29+
const should = window.localStorage.getItem('lnAnimate') || 'yes'
30+
if (should !== 'yes') return false
31+
animate()
32+
return true
33+
}, [animate])
34+
}
35+
36+
export function useAnimationEnabled () {
37+
const [enabled, setEnabled] = useState(undefined)
38+
39+
useEffect(() => {
40+
const enabled = window.localStorage.getItem('lnAnimate') || 'yes'
41+
setEnabled(enabled === 'yes')
42+
}, [])
43+
44+
const toggleEnabled = useCallback(() => {
45+
setEnabled(enabled => {
46+
const newEnabled = !enabled
47+
window.localStorage.setItem('lnAnimate', newEnabled ? 'yes' : 'no')
48+
return newEnabled
49+
})
50+
}, [])
51+
52+
return [enabled, toggleEnabled]
53+
}
54+
55+
function AnimationHooks ({ children }) {
56+
const { me } = useMe()
57+
const animate = useAnimation()
58+
59+
useEffect(() => {
60+
if (me || window.localStorage.getItem('striked') || window.localStorage.getItem('lnAnimated')) return
61+
62+
const timeout = setTimeout(() => {
63+
const animated = animate()
64+
if (animated) {
65+
window.localStorage.setItem('lnAnimated', 'yep')
66+
}
67+
}, randInRange(3000, 10000))
68+
return () => clearTimeout(timeout)
69+
}, [me?.id, animate])
70+
71+
return children
72+
}

components/lightning.js renamed to components/animation/lightning.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,11 @@ export class LightningProvider extends React.Component {
1313
* @returns boolean indicating whether the strike actually happened, based on user preferences
1414
*/
1515
strike = () => {
16-
const should = window.localStorage.getItem('lnAnimate') || 'yes'
17-
if (should === 'yes') {
18-
this.setState(state => {
19-
return {
20-
bolts: [...state.bolts, <Lightning key={state.bolts.length} onDone={() => this.unstrike(state.bolts.length)} />]
21-
}
22-
})
23-
return true
24-
}
25-
return false
16+
this.setState(state => {
17+
return {
18+
bolts: [...state.bolts, <Lightning key={state.bolts.length} onDone={() => this.unstrike(state.bolts.length)} />]
19+
}
20+
})
2621
}
2722

2823
unstrike = (index) => {

components/snow.js renamed to components/animation/snow.js

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,16 @@ export const SnowProvider = ({ children }) => {
1111
const [flakes, setFlakes] = useState(Array(1024))
1212

1313
const snow = useCallback(() => {
14-
const should = window.localStorage.getItem('lnAnimate') || 'yes'
15-
if (should === 'yes') {
16-
// amount of flakes to add
17-
const n = Math.floor(randInRange(5, 30))
18-
const newFlakes = [...flakes]
19-
let i
20-
for (i = startIndex; i < (startIndex + n); ++i) {
21-
const key = startIndex + i
22-
newFlakes[i % MAX_FLAKES] = <Snow key={key} />
23-
}
24-
setStartIndex(i % MAX_FLAKES)
25-
setFlakes(newFlakes)
26-
return true
14+
// amount of flakes to add
15+
const n = Math.floor(randInRange(5, 30))
16+
const newFlakes = [...flakes]
17+
let i
18+
for (i = startIndex; i < (startIndex + n); ++i) {
19+
const key = startIndex + i
20+
newFlakes[i % MAX_FLAKES] = <Snow key={key} />
2721
}
28-
return false
22+
setStartIndex(i % MAX_FLAKES)
23+
setFlakes(newFlakes)
2924
}, [setFlakes, startIndex])
3025

3126
return (

components/footer.js

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ import No from '@/svgs/no.svg'
1212
import Bolt from '@/svgs/bolt.svg'
1313
import Amboss from '@/svgs/amboss.svg'
1414
import Mempool from '@/svgs/bimi.svg'
15-
import { useEffect, useState } from 'react'
1615
import Rewards from './footer-rewards'
1716
import useDarkMode from './dark-mode'
1817
import ActionTooltip from './action-tooltip'
18+
import { useAnimationEnabled } from '@/components/animation'
1919

2020
const RssPopover = (
2121
<Popover>
@@ -145,24 +145,10 @@ const LegalPopover = (
145145
export default function Footer ({ links = true }) {
146146
const [darkMode, darkModeToggle] = useDarkMode()
147147

148-
const [lightning, setLightning] = useState(undefined)
149-
150-
useEffect(() => {
151-
setLightning(window.localStorage.getItem('lnAnimate') || 'yes')
152-
}, [])
153-
154-
const toggleLightning = () => {
155-
if (lightning === 'yes') {
156-
window.localStorage.setItem('lnAnimate', 'no')
157-
setLightning('no')
158-
} else {
159-
window.localStorage.setItem('lnAnimate', 'yes')
160-
setLightning('yes')
161-
}
162-
}
148+
const [animationEnabled, toggleAnimation] = useAnimationEnabled()
163149

164150
const DarkModeIcon = darkMode ? Sun : Moon
165-
const LnIcon = lightning === 'yes' ? No : Bolt
151+
const LnIcon = animationEnabled ? No : Bolt
166152

167153
const version = process.env.NEXT_PUBLIC_COMMIT_HASH
168154

@@ -175,8 +161,8 @@ export default function Footer ({ links = true }) {
175161
<ActionTooltip notForm overlayText={`${darkMode ? 'disable' : 'enable'} dark mode`}>
176162
<DarkModeIcon onClick={darkModeToggle} width={20} height={20} className='fill-grey theme' suppressHydrationWarning />
177163
</ActionTooltip>
178-
<ActionTooltip notForm overlayText={`${lightning === 'yes' ? 'disable' : 'enable'} lightning animations`}>
179-
<LnIcon onClick={toggleLightning} width={20} height={20} className='ms-2 fill-grey theme' suppressHydrationWarning />
164+
<ActionTooltip notForm overlayText={`${animationEnabled ? 'disable' : 'enable'} lightning animations`}>
165+
<LnIcon onClick={toggleAnimation} width={20} height={20} className='ms-2 fill-grey theme' suppressHydrationWarning />
180166
</ActionTooltip>
181167
</div>
182168
<div className='mb-0' style={{ fontWeight: 500 }}>

components/item-act.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { ACT_MUTATION } from '@/fragments/paidAction'
1313
import { meAnonSats } from '@/lib/apollo'
1414
import { BoostItemInput } from './adv-post-form'
1515
import { useSendWallets } from '@/wallets/index'
16-
import { useFireworks } from './fireworks'
16+
import { useAnimation } from '@/components/animation'
1717

1818
const defaultTips = [100, 1000, 10_000, 100_000]
1919

@@ -96,7 +96,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
9696
}, [onClose, item.id])
9797

9898
const actor = useAct()
99-
const strike = useFireworks()
99+
const animate = useAnimation()
100100

101101
const onSubmit = useCallback(async ({ amount }) => {
102102
if (abortSignal && zapUndoTrigger({ me, amount })) {
@@ -111,7 +111,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
111111
}
112112

113113
const onPaid = () => {
114-
strike()
114+
animate()
115115
onClose?.()
116116
if (!me) setItemMeAnonSats({ id: item.id, amount })
117117
}
@@ -143,7 +143,7 @@ export default function ItemAct ({ onClose, item, act = 'TIP', step, children, a
143143
})
144144
if (error) throw error
145145
addCustomTip(Number(amount))
146-
}, [me, actor, wallets.length, act, item.id, onClose, abortSignal, strike])
146+
}, [me, actor, wallets.length, act, item.id, onClose, abortSignal, animate])
147147

148148
return act === 'BOOST'
149149
? <BoostForm step={step} onSubmit={onSubmit} item={item} inputRef={inputRef} act={act}>{children}</BoostForm>
@@ -300,7 +300,7 @@ export function useAct ({ query = ACT_MUTATION, ...options } = {}) {
300300
export function useZap () {
301301
const wallets = useSendWallets()
302302
const act = useAct()
303-
const strike = useFireworks()
303+
const animate = useAnimation()
304304
const toaster = useToast()
305305

306306
return useCallback(async ({ item, me, abortSignal }) => {
@@ -314,7 +314,7 @@ export function useZap () {
314314

315315
try {
316316
await abortSignal.pause({ me, amount: sats })
317-
strike()
317+
animate()
318318
// batch zaps if wallet is enabled or using fee credits so they can be executed serially in a single request
319319
const { error } = await act({ variables, optimisticResponse, context: { batch: wallets.length > 0 || me?.privates?.sats > sats } })
320320
if (error) throw error
@@ -327,7 +327,7 @@ export function useZap () {
327327
// but right now this toast is noisy for optimistic zaps
328328
console.error(error)
329329
}
330-
}, [act, toaster, strike, wallets])
330+
}, [act, toaster, animate, wallets])
331331
}
332332

333333
export class ActCanceledError extends Error {

components/nav/common.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import { abbrNum } from '../../lib/format'
1414
import { useServiceWorker } from '../serviceworker'
1515
import { signOut } from 'next-auth/react'
1616
import Badges from '../badge'
17-
import { randInRange } from '../../lib/rand'
18-
import { useFireworks } from '../fireworks'
1917
import LightningIcon from '../../svgs/bolt.svg'
2018
import SearchIcon from '../../svgs/search-line.svg'
2119
import classNames from 'classnames'
@@ -400,20 +398,6 @@ export function LoginButtons ({ handleClose }) {
400398
}
401399

402400
export function AnonDropdown ({ path }) {
403-
const strike = useFireworks()
404-
405-
useEffect(() => {
406-
if (!window.localStorage.getItem('striked')) {
407-
const to = setTimeout(() => {
408-
const striked = strike()
409-
if (striked) {
410-
window.localStorage.setItem('striked', 'yep')
411-
}
412-
}, randInRange(3000, 10000))
413-
return () => clearTimeout(to)
414-
}
415-
}, [])
416-
417401
return (
418402
<div className='position-relative'>
419403
<Dropdown className={styles.dropdown} align='end' autoClose>

components/pay-bounty.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { numWithUnits } from '@/lib/format'
66
import { useShowModal } from './modal'
77
import { useRoot } from './root'
88
import { ActCanceledError, useAct } from './item-act'
9-
import { useFireworks } from './fireworks'
9+
import { useAnimation } from '@/components/animation'
1010
import { useToast } from './toast'
1111
import { useSendWallets } from '@/wallets/index'
1212
import { Form, SubmitButton } from './form'
@@ -48,7 +48,7 @@ export default function PayBounty ({ children, item }) {
4848
const { me } = useMe()
4949
const showModal = useShowModal()
5050
const root = useRoot()
51-
const strike = useFireworks()
51+
const animate = useAnimation()
5252
const toaster = useToast()
5353
const wallets = useSendWallets()
5454

@@ -61,7 +61,7 @@ export default function PayBounty ({ children, item }) {
6161

6262
const handlePayBounty = async onCompleted => {
6363
try {
64-
strike()
64+
animate()
6565
const { error } = await act({ onCompleted })
6666
if (error) throw error
6767
} catch (error) {

pages/_app.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useRouter } from 'next/dist/client/router'
1010
import { useCallback, useEffect } from 'react'
1111
import { ShowModalProvider } from '@/components/modal'
1212
import ErrorBoundary from '@/components/error-boundary'
13-
import { FireworksProvider } from '@/components/fireworks'
13+
import { AnimationProvider } from '@/components/animation'
1414
import { ToastProvider } from '@/components/toast'
1515
import { ServiceWorkerProvider } from '@/components/serviceworker'
1616
import { SSR } from '@/lib/constants'
@@ -116,7 +116,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
116116
<WebLnProvider>
117117
<ServiceWorkerProvider>
118118
<PriceProvider price={price}>
119-
<FireworksProvider>
119+
<AnimationProvider>
120120
<ToastProvider>
121121
<ShowModalProvider>
122122
<BlockHeightProvider blockHeight={blockHeight}>
@@ -129,7 +129,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) {
129129
</BlockHeightProvider>
130130
</ShowModalProvider>
131131
</ToastProvider>
132-
</FireworksProvider>
132+
</AnimationProvider>
133133
</PriceProvider>
134134
</ServiceWorkerProvider>
135135
</WebLnProvider>

0 commit comments

Comments
 (0)