diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index b28b9f5a25..2d9a41085d 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -1,19 +1,27 @@ import React from 'react' import {useDialogStateContext} from '#/state/dialogs' -import {DialogContextProps, DialogControlProps} from '#/components/Dialog/types' +import { + DialogContextProps, + DialogControlProps, + DialogControlWithRefProps, + DialogParams, +} from '#/components/Dialog/types' -export const Context = React.createContext({ +export const Context = React.createContext>({ + params: {}, close: () => {}, }) -export function useDialogContext() { - return React.useContext(Context) +export function useDialogContext() { + return React.useContext(Context) as DialogContextProps } -export function useDialogControl() { +export function useDialogControl< + Params extends DialogParams, +>(): DialogControlWithRefProps { const id = React.useId() - const control = React.useRef({ + const control = React.useRef>({ open: () => {}, close: () => {}, }) @@ -29,7 +37,7 @@ export function useDialogControl() { return { ref: control, - open: () => control.current.open(), + open: (params, options) => control.current.open(params, options), close: () => control.current.close(), } } diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 44e4dc8a70..162f020119 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -16,6 +16,7 @@ import { DialogOuterProps, DialogControlProps, DialogInnerProps, + DialogParams, } from '#/components/Dialog/types' import {Context} from '#/components/Dialog/context' @@ -24,20 +25,28 @@ export * from '#/components/Dialog/types' // @ts-ignore export const Input = createInput(BottomSheetTextInput) -export function Outer({ +export function Outer({ children, control, onClose, nativeOptions, -}: React.PropsWithChildren) { +}: React.PropsWithChildren>) { const t = useTheme() const sheet = React.useRef(null) const sheetOptions = nativeOptions?.sheet || {} const hasSnapPoints = !!sheetOptions.snapPoints + const [params, setParams] = React.useState({}) - const open = React.useCallback((i = 0) => { - sheet.current?.snapToIndex(i) - }, []) + const open = React.useCallback['open']>( + (params, {snapIndex} = {}) => { + if (params) { + console.log({params}) + setParams(params) + } + sheet.current?.snapToIndex(snapIndex || 0) + }, + [setParams], + ) const close = React.useCallback(() => { sheet.current?.close() @@ -53,7 +62,7 @@ export function Outer({ [open, close], ) - const context = React.useMemo(() => ({close}), [close]) + const context = React.useMemo(() => ({close, params}), [close, params]) return ( diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx index 305c00e97a..cb6703f058 100644 --- a/src/components/Dialog/index.web.tsx +++ b/src/components/Dialog/index.web.tsx @@ -8,7 +8,12 @@ import {useLingui} from '@lingui/react' import {useTheme, atoms as a, useBreakpoints, web} from '#/alf' import {Portal} from '#/components/Portal' -import {DialogOuterProps, DialogInnerProps} from '#/components/Dialog/types' +import { + DialogOuterProps, + DialogInnerProps, + DialogControlProps, + DialogParams, +} from '#/components/Dialog/types' import {Context} from '#/components/Dialog/context' export {useDialogControl, useDialogContext} from '#/components/Dialog/context' @@ -17,20 +22,27 @@ export {Input} from '#/components/forms/TextField' const stopPropagation = (e: any) => e.stopPropagation() -export function Outer({ +export function Outer({ control, onClose, children, -}: React.PropsWithChildren) { +}: React.PropsWithChildren>) { const {_} = useLingui() const t = useTheme() const {gtMobile} = useBreakpoints() const [isOpen, setIsOpen] = React.useState(false) const [isVisible, setIsVisible] = React.useState(true) + const [params, setParams] = React.useState({}) - const open = React.useCallback(() => { - setIsOpen(true) - }, [setIsOpen]) + const open = React.useCallback['open']>( + params => { + if (params) { + setParams(params) + } + setIsOpen(true) + }, + [setIsOpen, setParams], + ) const close = React.useCallback(async () => { setIsVisible(false) @@ -63,9 +75,10 @@ export function Outer({ const context = React.useMemo( () => ({ + params, close, }), - [close], + [close, params], ) return ( diff --git a/src/components/Dialog/types.ts b/src/components/Dialog/types.ts index d36784183c..d9ab4a2e44 100644 --- a/src/components/Dialog/types.ts +++ b/src/components/Dialog/types.ts @@ -4,21 +4,24 @@ import {BottomSheetProps} from '@gorhom/bottom-sheet' type A11yProps = Required -export type DialogContextProps = { +export type DialogParams = Record + +export type DialogContextProps = { + params: Params close: () => void } -export type DialogControlProps = { - open: (index?: number) => void +export type DialogControlProps = { + open: (params?: Params, options?: {snapIndex?: number}) => void close: () => void } -export type DialogOuterProps = { - control: { - ref: React.RefObject - open: (index?: number) => void - close: () => void - } +export type DialogControlWithRefProps = { + ref: React.RefObject> +} & DialogControlProps + +export type DialogOuterProps = { + control: DialogControlWithRefProps onClose?: () => void nativeOptions?: { sheet?: Omit diff --git a/src/components/dialogs/ReportDialog/index.tsx b/src/components/dialogs/ReportDialog/index.tsx new file mode 100644 index 0000000000..6d720f83b3 --- /dev/null +++ b/src/components/dialogs/ReportDialog/index.tsx @@ -0,0 +1,39 @@ +import React from 'react' + +import * as Dialog from '#/components/Dialog' +import {Text} from '#/components/Typography' +import {Context} from '#/components/dialogs' + +export type DialogParams = + | { + type: 'post' + uri: string + cid: string + } + | { + type: 'user' + did: string + } + +export function useReportDialogControl() { + return React.useContext(Context).report +} + +export function ReportDialog() { + const control = useReportDialogControl() + + return ( + + + + + + + + ) +} + +function Inner() { + const ctx = Dialog.useDialogContext() + return hello {JSON.stringify(ctx.params)} +} diff --git a/src/components/dialogs/index.tsx b/src/components/dialogs/index.tsx new file mode 100644 index 0000000000..67d4c7f40c --- /dev/null +++ b/src/components/dialogs/index.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +import * as Dialog from '#/components/Dialog' + +import {DialogParams as ReportDialogParams} from '#/components/dialogs/ReportDialog' + +/** + * Global dialog context. Name each dialog and specify its parameters. + */ +type Context = { + report: Dialog.DialogControlWithRefProps +} + +/** + * Global dialog context. + */ +export const Context = React.createContext({} as Context) + +/** + * Global dialog context provider. + */ +export function Provider({children}: React.PropsWithChildren<{}>) { + const report = Dialog.useDialogControl() + const ctx = React.useMemo( + () => ({ + report, + }), + [report], + ) + + return {children} +} diff --git a/src/state/dialogs/index.tsx b/src/state/dialogs/index.tsx index 4cafaa0861..2aa89b5c89 100644 --- a/src/state/dialogs/index.tsx +++ b/src/state/dialogs/index.tsx @@ -1,5 +1,6 @@ import React from 'react' import {DialogControlProps} from '#/components/Dialog' +import {Provider as GlobalDialogsProvider} from '#/components/dialogs' const DialogContext = React.createContext<{ activeDialogs: React.MutableRefObject< @@ -27,7 +28,7 @@ export function useDialogStateControlContext() { export function Provider({children}: React.PropsWithChildren<{}>) { const activeDialogs = React.useRef< - Map> + Map>> >(new Map()) const closeAllDialogs = React.useCallback(() => { activeDialogs.current.forEach(dialog => dialog.current.close()) @@ -37,7 +38,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { return ( - {children} + {children} ) diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx index e56c88d2c9..0392d94647 100644 --- a/src/view/com/util/forms/PostDropdownBtn.tsx +++ b/src/view/com/util/forms/PostDropdownBtn.tsx @@ -31,6 +31,7 @@ import {useLingui} from '@lingui/react' import {useSession} from '#/state/session' import {isWeb} from '#/platform/detection' import {richTextToString} from '#/lib/strings/rich-text-helpers' +import {useReportDialogControl} from '#/components/dialogs/ReportDialog' let PostDropdownBtn = ({ testID, @@ -63,6 +64,7 @@ let PostDropdownBtn = ({ const hiddenPosts = useHiddenPosts() const {hidePost} = useHiddenPostsApi() const openLink = useOpenLink() + const reportDialogControl = useReportDialogControl() const rootUri = record.reply?.root?.uri || postUri const isThreadMuted = mutedThreads.includes(rootUri) @@ -209,11 +211,12 @@ let PostDropdownBtn = ({ hasSession && { label: _(msg`Report post`), onPress() { - openModal({ - name: 'report', - uri: postUri, - cid: postCid, - }) + reportDialogControl.open({type: 'post', uri: postUri, cid: postCid}) + // openModal({ + // name: 'report', + // uri: postUri, + // cid: postCid, + // }) }, testID: 'postDropdownReportBtn', icon: { diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index 6b0cc68089..2954921ad7 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -29,6 +29,7 @@ import {useSession} from '#/state/session' import {useCloseAnyActiveElement} from '#/state/util' import * as notifications from 'lib/notifications/notifications' import {Outlet as PortalOutlet} from '#/components/Portal' +import {ReportDialog} from '#/components/dialogs/ReportDialog' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -94,8 +95,10 @@ function ShellInner() { - + + + ) } diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 97c0655022..50d91a3557 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -16,6 +16,7 @@ import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' import {useCloseAllActiveElements} from '#/state/util' import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock' import {Outlet as PortalOutlet} from '#/components/Portal' +import {ReportDialog} from '#/components/dialogs/ReportDialog' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -40,8 +41,11 @@ function ShellInner() { - + + + + {!isDesktop && isDrawerOpen && ( setDrawerOpen(false)}