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 DeleteAccountModal {
15 name: 'delete-account'
16}
17
18export interface ContentLanguagesSettingsModal {
19 name: 'content-languages-settings'
20}
21
22/**
23 * @deprecated DO NOT ADD NEW MODALS
24 */
25export type Modal =
26 // Account
27 | DeleteAccountModal
28
29 // Curation
30 | ContentLanguagesSettingsModal
31
32 // Lists
33 | UserAddRemoveListsModal
34
35const ModalContext = React.createContext<{
36 isModalActive: boolean
37 activeModals: Modal[]
38}>({
39 isModalActive: false,
40 activeModals: [],
41})
42ModalContext.displayName = 'ModalContext'
43
44const ModalControlContext = React.createContext<{
45 openModal: (modal: Modal) => void
46 closeModal: () => boolean
47 closeAllModals: () => boolean
48}>({
49 openModal: () => {},
50 closeModal: () => false,
51 closeAllModals: () => false,
52})
53ModalControlContext.displayName = 'ModalControlContext'
54
55export function Provider({children}: React.PropsWithChildren<{}>) {
56 const [activeModals, setActiveModals] = React.useState<Modal[]>([])
57
58 const openModal = useNonReactiveCallback((modal: Modal) => {
59 setActiveModals(modals => [...modals, modal])
60 })
61
62 const closeModal = useNonReactiveCallback(() => {
63 let wasActive = activeModals.length > 0
64 setActiveModals(modals => {
65 return modals.slice(0, -1)
66 })
67 return wasActive
68 })
69
70 const closeAllModals = useNonReactiveCallback(() => {
71 let wasActive = activeModals.length > 0
72 setActiveModals([])
73 return wasActive
74 })
75
76 const state = React.useMemo(
77 () => ({
78 isModalActive: activeModals.length > 0,
79 activeModals,
80 }),
81 [activeModals],
82 )
83
84 const methods = React.useMemo(
85 () => ({
86 openModal,
87 closeModal,
88 closeAllModals,
89 }),
90 [openModal, closeModal, closeAllModals],
91 )
92
93 return (
94 <ModalContext.Provider value={state}>
95 <ModalControlContext.Provider value={methods}>
96 {children}
97 </ModalControlContext.Provider>
98 </ModalContext.Provider>
99 )
100}
101
102/**
103 * @deprecated use the dialog system from `#/components/Dialog.tsx`
104 */
105export function useModals() {
106 return React.useContext(ModalContext)
107}
108
109/**
110 * @deprecated use the dialog system from `#/components/Dialog.tsx`
111 */
112export function useModalControls() {
113 return React.useContext(ModalControlContext)
114}