import * as React from 'react'; import { createContext, useEffect, useMemo, useRef, useState } from 'react'; import { StyleSheet, useWindowDimensions } from 'react-native'; import { Portal } from 'react-native-paper'; import Modal from '../Modal'; import shim from '@joplin/lib/shim'; import makeShowMessageBox from '../../utils/makeShowMessageBox'; import { DialogControl, DialogData, DialogType } from './types'; import useDialogControl from './hooks/useDialogControl'; import PromptDialog from './PromptDialog'; import { themeStyle } from '../global-style'; import TextInputDialog from './TextInputDialog'; export type { DialogControl } from './types'; export const DialogContext = createContext(null); interface Props { themeId: number; children: React.ReactNode; } const useStyles = (themeId: number) => { const windowSize = useWindowDimensions(); return useMemo(() => { const theme = themeStyle(themeId); return StyleSheet.create({ modalContainer: { marginLeft: 'auto', marginRight: 'auto', marginTop: 'auto', marginBottom: 'auto', width: Math.max(windowSize.width / 2, 400), maxWidth: '100%', }, dialogContainer: { backgroundColor: theme.backgroundColor, borderRadius: theme.borderRadius, paddingTop: theme.borderRadius, marginLeft: 4, marginRight: 4, }, }); }, [windowSize.width, themeId]); }; const DialogManager: React.FC = props => { const [dialogModels, setPromptDialogs] = useState([]); const dialogControl = useDialogControl(setPromptDialogs); const dialogControlRef = useRef(dialogControl); dialogControlRef.current = dialogControl; useEffect(() => { shim.showMessageBox = makeShowMessageBox(dialogControlRef); return () => { dialogControlRef.current = null; }; }, []); const theme = themeStyle(props.themeId); const styles = useStyles(props.themeId); const dialogComponents: React.ReactNode[] = []; for (const dialog of dialogModels) { const dialogProps = { containerStyle: styles.dialogContainer, themeId: props.themeId, }; if (dialog.type === DialogType.Menu || dialog.type === DialogType.ButtonPrompt) { dialogComponents.push( , ); } else if (dialog.type === DialogType.TextInput) { dialogComponents.push( , ); } else { const exhaustivenessCheck: never = dialog.type; throw new Error(`Unexpected dialog type ${exhaustivenessCheck}`); } } // Web: Use a wrapper for better keyboard focus handling. return <> {props.children} {dialogComponents} ; }; export default DialogManager;