forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React from 'react'
2import {nanoid} from 'nanoid/non-secure'
3
4import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
5import {type ImageSource} from '#/view/com/lightbox/ImageViewing/@types'
6
7export type Lightbox = {
8 id: string
9 images: ImageSource[]
10 index: number
11}
12
13const LightboxContext = React.createContext<{
14 activeLightbox: Lightbox | null
15}>({
16 activeLightbox: null,
17})
18LightboxContext.displayName = 'LightboxContext'
19
20const LightboxControlContext = React.createContext<{
21 openLightbox: (lightbox: Omit<Lightbox, 'id'>) => void
22 closeLightbox: () => boolean
23}>({
24 openLightbox: () => {},
25 closeLightbox: () => false,
26})
27LightboxControlContext.displayName = 'LightboxControlContext'
28
29export function Provider({children}: React.PropsWithChildren<{}>) {
30 const [activeLightbox, setActiveLightbox] = React.useState<Lightbox | null>(
31 null,
32 )
33
34 const openLightbox = useNonReactiveCallback(
35 (lightbox: Omit<Lightbox, 'id'>) => {
36 setActiveLightbox(prevLightbox => {
37 if (prevLightbox) {
38 // Ignore duplicate open requests. If it's already open,
39 // the user has to explicitly close the previous one first.
40 return prevLightbox
41 } else {
42 return {...lightbox, id: nanoid()}
43 }
44 })
45 },
46 )
47
48 const closeLightbox = useNonReactiveCallback(() => {
49 let wasActive = !!activeLightbox
50 setActiveLightbox(null)
51 return wasActive
52 })
53
54 const state = React.useMemo(
55 () => ({
56 activeLightbox,
57 }),
58 [activeLightbox],
59 )
60
61 const methods = React.useMemo(
62 () => ({
63 openLightbox,
64 closeLightbox,
65 }),
66 [openLightbox, closeLightbox],
67 )
68
69 return (
70 <LightboxContext.Provider value={state}>
71 <LightboxControlContext.Provider value={methods}>
72 {children}
73 </LightboxControlContext.Provider>
74 </LightboxContext.Provider>
75 )
76}
77
78export function useLightbox() {
79 return React.useContext(LightboxContext)
80}
81
82export function useLightboxControls() {
83 return React.useContext(LightboxControlContext)
84}