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