Skip to content

Commit 96fd271

Browse files
authored
add fireworks (#2258)
* add fireworks * fix weird search background color due to canvas overlay * prevent going off small screens
1 parent de01d94 commit 96fd271

File tree

13 files changed

+541
-17
lines changed

13 files changed

+541
-17
lines changed

components/fireworks.js

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
import { useCallback, createContext, useContext, useState, useEffect } from 'react'
2+
import Particles from 'react-particles'
3+
import { loadFireworksPreset } from 'tsparticles-preset-fireworks'
4+
import styles from './fireworks.module.css'
5+
import {
6+
rgbToHsl,
7+
setRangeValue,
8+
stringToRgb
9+
} from 'tsparticles-engine'
10+
import useDarkMode from './dark-mode'
11+
12+
export const FireworksContext = createContext({
13+
strike: () => {}
14+
})
15+
16+
export const FireworksConsumer = FireworksContext.Consumer
17+
export function useFireworks () {
18+
const { strike } = useContext(FireworksContext)
19+
return strike
20+
}
21+
22+
export function FireworksProvider ({ children }) {
23+
const [cont, setCont] = useState()
24+
const [context, setContext] = useState({ strike: () => {} })
25+
const [darkMode] = useDarkMode()
26+
27+
useEffect(() => {
28+
setContext({
29+
strike: () => {
30+
cont?.addEmitter(
31+
{
32+
direction: 'top',
33+
life: {
34+
count: 1,
35+
duration: 0.1,
36+
delay: 0.1
37+
},
38+
rate: {
39+
delay: 0,
40+
quantity: 1
41+
},
42+
size: {
43+
width: 10,
44+
height: 0
45+
},
46+
position: {
47+
y: 100,
48+
x: 50
49+
}
50+
})
51+
return true
52+
}
53+
})
54+
}, [cont])
55+
56+
const particlesLoaded = useCallback((container) => {
57+
setCont(container)
58+
}, [])
59+
60+
const particlesInit = useCallback(async engine => {
61+
// you can initiate the tsParticles instance (engine) here, adding custom shapes or presets
62+
// this loads the tsparticles package bundle, it's the easiest method for getting everything ready
63+
// starting from v2 you can add only the features you need reducing the bundle size
64+
await loadFireworksPreset(engine)
65+
}, [])
66+
67+
return (
68+
<FireworksContext.Provider value={context}>
69+
<Particles
70+
className={styles.fireworks}
71+
init={particlesInit}
72+
loaded={particlesLoaded}
73+
options={darkMode ? darkOptions : lightOptions}
74+
/>
75+
{children}
76+
</FireworksContext.Provider>
77+
)
78+
}
79+
80+
const fixRange = (value, min, max) => {
81+
const diffSMax = value.max > max ? value.max - max : 0
82+
let res = setRangeValue(value)
83+
84+
if (diffSMax) {
85+
res = setRangeValue(value.min - diffSMax, max)
86+
}
87+
88+
const diffSMin = value.min < min ? value.min : 0
89+
90+
if (diffSMin) {
91+
res = setRangeValue(0, value.max + diffSMin)
92+
}
93+
94+
return res
95+
}
96+
97+
const fireworksOptions = ['#ff595e', '#ffca3a', '#8ac926', '#1982c4', '#6a4c93']
98+
.map((color) => {
99+
const rgb = stringToRgb(color)
100+
101+
if (!rgb) {
102+
return undefined
103+
}
104+
105+
const hsl = rgbToHsl(rgb)
106+
const sRange = fixRange({ min: hsl.s - 30, max: hsl.s + 30 }, 0, 100)
107+
const lRange = fixRange({ min: hsl.l - 30, max: hsl.l + 30 }, 0, 100)
108+
109+
return {
110+
color: {
111+
value: {
112+
h: hsl.h,
113+
s: sRange,
114+
l: lRange
115+
}
116+
},
117+
stroke: {
118+
width: 0
119+
},
120+
number: {
121+
value: 0
122+
},
123+
opacity: {
124+
value: {
125+
min: 0.1,
126+
max: 1
127+
},
128+
animation: {
129+
enable: true,
130+
speed: 0.7,
131+
sync: false,
132+
startValue: 'max',
133+
destroy: 'min'
134+
}
135+
},
136+
shape: {
137+
type: 'circle'
138+
},
139+
size: {
140+
value: { min: 1, max: 2 },
141+
animation: {
142+
enable: true,
143+
speed: 5,
144+
count: 1,
145+
sync: false,
146+
startValue: 'min',
147+
destroy: 'none'
148+
}
149+
},
150+
life: {
151+
count: 1,
152+
duration: {
153+
value: {
154+
min: 1,
155+
max: 2
156+
}
157+
}
158+
},
159+
move: {
160+
decay: { min: 0.075, max: 0.1 },
161+
enable: true,
162+
gravity: {
163+
enable: true,
164+
inverse: false,
165+
acceleration: 5
166+
},
167+
speed: { min: 5, max: 15 },
168+
direction: 'none',
169+
outMode: {
170+
top: 'destroy',
171+
default: 'bounce'
172+
}
173+
}
174+
}
175+
})
176+
.filter((t) => t !== undefined)
177+
178+
const particlesOptions = (theme) => ({
179+
number: {
180+
value: 0
181+
},
182+
destroy: {
183+
mode: 'split',
184+
bounds: {
185+
top: { min: 5, max: 40 }
186+
},
187+
split: {
188+
sizeOffset: false,
189+
count: 1,
190+
factor: {
191+
value: 0.333333
192+
},
193+
rate: {
194+
value: { min: 75, max: 150 }
195+
},
196+
particles: fireworksOptions
197+
}
198+
},
199+
life: {
200+
count: 1
201+
},
202+
shape: {
203+
type: 'line'
204+
},
205+
size: {
206+
value: {
207+
min: 0.1,
208+
max: 50
209+
},
210+
animation: {
211+
enable: true,
212+
sync: true,
213+
speed: 90,
214+
startValue: 'max',
215+
destroy: 'min'
216+
}
217+
},
218+
rotate: {
219+
path: true
220+
},
221+
stroke: {
222+
color: {
223+
value: theme === 'dark' ? '#fff' : '#aaa'
224+
},
225+
width: 1
226+
},
227+
move: {
228+
enable: true,
229+
gravity: {
230+
acceleration: 15,
231+
enable: true,
232+
inverse: true,
233+
maxSpeed: 100
234+
},
235+
speed: {
236+
min: 10,
237+
max: 20
238+
},
239+
outModes: {
240+
default: 'split',
241+
top: 'none'
242+
},
243+
trail: {
244+
fillColor: theme === 'dark' ? '#000' : '#f5f5f7',
245+
enable: true,
246+
length: 10
247+
}
248+
}
249+
})
250+
251+
const darkOptions = {
252+
fullScreen: { enable: true, zIndex: -1 },
253+
detectRetina: true,
254+
background: {
255+
color: '#000',
256+
opacity: 0
257+
},
258+
fpsLimit: 120,
259+
emitters: [],
260+
particles: particlesOptions('dark')
261+
}
262+
263+
const lightOptions = {
264+
fullScreen: { enable: true, zIndex: -1 },
265+
detectRetina: true,
266+
background: {
267+
color: '#fff',
268+
opacity: 0
269+
},
270+
fpsLimit: 120,
271+
emitters: [],
272+
particles: particlesOptions('light')
273+
}

components/fireworks.module.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.fireworks {
2+
z-index: 0;
3+
position: fixed;
4+
top: 0;
5+
left: 0;
6+
width: 100vw;
7+
height: 100vh;
8+
}

components/item-act.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import { useMe } from './me'
66
import UpBolt from '@/svgs/bolt.svg'
77
import { amountSchema, boostSchema } from '@/lib/validate'
88
import { useToast } from './toast'
9-
import { useLightning } from './lightning'
109
import { nextTip, defaultTipIncludingRandom } from './upvote'
1110
import { ZAP_UNDO_DELAY_MS } from '@/lib/constants'
1211
import { usePaidMutation } from './use-paid-mutation'
1312
import { ACT_MUTATION } from '@/fragments/paidAction'
1413
import { meAnonSats } from '@/lib/apollo'
1514
import { BoostItemInput } from './adv-post-form'
1615
import { useSendWallets } from '@/wallets/index'
16+
import { useFireworks } from './fireworks'
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 = useLightning()
99+
const strike = useFireworks()
100100

101101
const onSubmit = useCallback(async ({ amount }) => {
102102
if (abortSignal && zapUndoTrigger({ me, amount })) {
@@ -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 = useLightning()
303+
const strike = useFireworks()
304304
const toaster = useToast()
305305

306306
return useCallback(async ({ item, me, abortSignal }) => {

components/layout.module.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
height: 100%;
66
align-items: center;
77
margin: auto;
8+
z-index: 0;
89
}
910

1011
.content {

components/nav/common.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { useServiceWorker } from '../serviceworker'
1515
import { signOut } from 'next-auth/react'
1616
import Badges from '../badge'
1717
import { randInRange } from '../../lib/rand'
18-
import { useLightning } from '../lightning'
18+
import { useFireworks } from '../fireworks'
1919
import LightningIcon from '../../svgs/bolt.svg'
2020
import SearchIcon from '../../svgs/search-line.svg'
2121
import classNames from 'classnames'
@@ -400,13 +400,15 @@ export function LoginButtons ({ handleClose }) {
400400
}
401401

402402
export function AnonDropdown ({ path }) {
403-
const strike = useLightning()
403+
const strike = useFireworks()
404404

405405
useEffect(() => {
406406
if (!window.localStorage.getItem('striked')) {
407407
const to = setTimeout(() => {
408-
strike()
409-
window.localStorage.setItem('striked', 'yep')
408+
const striked = strike()
409+
if (striked) {
410+
window.localStorage.setItem('striked', 'yep')
411+
}
410412
}, randInRange(3000, 10000))
411413
return () => clearTimeout(to)
412414
}

components/pay-bounty.js

Lines changed: 2 additions & 2 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 { useLightning } from './lightning'
9+
import { useFireworks } from './fireworks'
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 = useLightning()
51+
const strike = useFireworks()
5252
const toaster = useToast()
5353
const wallets = useSendWallets()
5454

components/search.module.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.searchSection {
2-
background-color: var(--bs-body-bg);
32
z-index: 1;
43
}
54

0 commit comments

Comments
 (0)