forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {createContext, useContext, useMemo, useState} from 'react'
2
3import {type AgeAssuranceRedirectDialogState} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
4import * as Dialog from '#/components/Dialog'
5import {type Screen} from '#/components/dialogs/EmailDialog/types'
6
7type Control = Dialog.DialogControlProps
8
9export type StatefulControl<T> = {
10 control: Control
11 open: (value: T) => void
12 clear: () => void
13 value: T | undefined
14}
15
16type ControlsContext = {
17 mutedWordsDialogControl: Control
18 signinDialogControl: Control
19 inAppBrowserConsentControl: StatefulControl<string>
20 emailDialogControl: StatefulControl<Screen>
21 linkWarningDialogControl: StatefulControl<{
22 href: string
23 displayText: string
24 share?: boolean
25 }>
26 ageAssuranceRedirectDialogControl: StatefulControl<AgeAssuranceRedirectDialogState>
27}
28
29const ControlsContext = createContext<ControlsContext | null>(null)
30ControlsContext.displayName = 'GlobalDialogControlsContext'
31
32export function useGlobalDialogsControlContext() {
33 const ctx = useContext(ControlsContext)
34 if (!ctx) {
35 throw new Error(
36 'useGlobalDialogsControlContext must be used within a Provider',
37 )
38 }
39 return ctx
40}
41
42export function Provider({children}: React.PropsWithChildren<{}>) {
43 const mutedWordsDialogControl = Dialog.useDialogControl()
44 const signinDialogControl = Dialog.useDialogControl()
45 const inAppBrowserConsentControl = useStatefulDialogControl<string>()
46 const emailDialogControl = useStatefulDialogControl<Screen>()
47 const linkWarningDialogControl = useStatefulDialogControl<{
48 href: string
49 displayText: string
50 share?: boolean
51 }>()
52 const ageAssuranceRedirectDialogControl =
53 useStatefulDialogControl<AgeAssuranceRedirectDialogState>()
54
55 const ctx = useMemo<ControlsContext>(
56 () => ({
57 mutedWordsDialogControl,
58 signinDialogControl,
59 inAppBrowserConsentControl,
60 emailDialogControl,
61 linkWarningDialogControl,
62 ageAssuranceRedirectDialogControl,
63 }),
64 [
65 mutedWordsDialogControl,
66 signinDialogControl,
67 inAppBrowserConsentControl,
68 emailDialogControl,
69 linkWarningDialogControl,
70 ageAssuranceRedirectDialogControl,
71 ],
72 )
73
74 return (
75 <ControlsContext.Provider value={ctx}>{children}</ControlsContext.Provider>
76 )
77}
78
79export function useStatefulDialogControl<T>(
80 initialValue?: T,
81): StatefulControl<T> {
82 const [value, setValue] = useState(initialValue)
83 const control = Dialog.useDialogControl()
84 return useMemo(
85 () => ({
86 control,
87 open: (v: T) => {
88 setValue(v)
89 control.open()
90 },
91 clear: () => setValue(initialValue),
92 value,
93 }),
94 [control, value, initialValue],
95 )
96}