forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React from 'react'
2
3import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
4
5export interface UserAddRemoveListsModal {
6 name: 'user-add-remove-lists'
7 subject: string
8 handle: string
9 displayName: string
10 onAdd?: (listUri: string) => void
11 onRemove?: (listUri: string) => void
12}
13
14export interface ContentLanguagesSettingsModal {
15 name: 'content-languages-settings'
16}
17
18/**
19 * @deprecated DO NOT ADD NEW MODALS
20 */
21export type Modal =
22 // Curation
23 | ContentLanguagesSettingsModal
24
25 // Lists
26 | UserAddRemoveListsModal
27
28const ModalContext = React.createContext<{
29 isModalActive: boolean
30 activeModals: Modal[]
31}>({
32 isModalActive: false,
33 activeModals: [],
34})
35ModalContext.displayName = 'ModalContext'
36
37const ModalControlContext = React.createContext<{
38 openModal: (modal: Modal) => void
39 closeModal: () => boolean
40 closeAllModals: () => boolean
41}>({
42 openModal: () => {},
43 closeModal: () => false,
44 closeAllModals: () => false,
45})
46ModalControlContext.displayName = 'ModalControlContext'
47
48export function Provider({children}: React.PropsWithChildren<{}>) {
49 const [activeModals, setActiveModals] = React.useState<Modal[]>([])
50
51 const openModal = useNonReactiveCallback((modal: Modal) => {
52 setActiveModals(modals => [...modals, modal])
53 })
54
55 const closeModal = useNonReactiveCallback(() => {
56 let wasActive = activeModals.length > 0
57 setActiveModals(modals => {
58 return modals.slice(0, -1)
59 })
60 return wasActive
61 })
62
63 const closeAllModals = useNonReactiveCallback(() => {
64 let wasActive = activeModals.length > 0
65 setActiveModals([])
66 return wasActive
67 })
68
69 const state = React.useMemo(
70 () => ({
71 isModalActive: activeModals.length > 0,
72 activeModals,
73 }),
74 [activeModals],
75 )
76
77 const methods = React.useMemo(
78 () => ({
79 openModal,
80 closeModal,
81 closeAllModals,
82 }),
83 [openModal, closeModal, closeAllModals],
84 )
85
86 return (
87 <ModalContext.Provider value={state}>
88 <ModalControlContext.Provider value={methods}>
89 {children}
90 </ModalControlContext.Provider>
91 </ModalContext.Provider>
92 )
93}
94
95/**
96 * @deprecated use the dialog system from `#/components/Dialog.tsx`
97 */
98export function useModals() {
99 return React.useContext(ModalContext)
100}
101
102/**
103 * @deprecated use the dialog system from `#/components/Dialog.tsx`
104 */
105export function useModalControls() {
106 return React.useContext(ModalControlContext)
107}