import * as React from 'react'; import PromptDialog from '../PromptDialog'; import ShareFolderDialog from '../ShareFolderDialog/ShareFolderDialog'; import NotePropertiesDialog from '../NotePropertiesDialog'; import NoteContentPropertiesDialog from '../NoteContentPropertiesDialog'; import ShareNoteDialog from '../ShareNoteDialog'; import { PluginHtmlContents, PluginStates } from '@joplin/lib/services/plugins/reducer'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { DialogState } from './types'; import { connect } from 'react-redux'; import { AppState, AppStateDialog, VisibleDialogs } from '../../app.reducer'; import { Dispatch } from 'redux'; import ModalMessageOverlay from './ModalMessageOverlay'; import { EditorNoteStatuses, stateUtils } from '@joplin/lib/reducer'; import dialogs from '../dialogs'; import useDocument from '../hooks/useDocument'; import useWindowCommands from './utils/useWindowCommands'; import PluginDialogs from './PluginDialogs'; import useSyncDialogState from './utils/useSyncDialogState'; import AppDialogs from './AppDialogs'; const PluginManager = require('@joplin/lib/services/PluginManager'); interface Props { dispatch: Dispatch; themeId: number; plugins: PluginStates; pluginHtmlContents: PluginHtmlContents; visibleDialogs: VisibleDialogs; appDialogStates: AppStateDialog[]; pluginsLegacy: unknown; modalMessage: string|null; customCss: string; editorNoteStatuses: EditorNoteStatuses; } const defaultDialogState: DialogState = { noteContentPropertiesDialogOptions: { visible: false, }, shareNoteDialogOptions: { visible: false, }, notePropertiesDialogOptions: { visible: false, }, shareFolderDialogOptions: { visible: false, }, promptOptions: null, }; // Certain dialog libraries need a reference to the active window: const useSyncActiveWindow = (containerWindow: Window|null) => { useEffect(() => { if (!containerWindow) return () => {}; const onFocusCallback = () => { dialogs.setActiveWindow(containerWindow); }; if (containerWindow.document.hasFocus()) { onFocusCallback(); } containerWindow.addEventListener('focus', onFocusCallback); return () => { containerWindow.removeEventListener('focus', onFocusCallback); }; }, [containerWindow]); }; const WindowCommandsAndDialogs: React.FC = props => { const [referenceElement, setReferenceElement] = useState(null); const containerDocument = useDocument(referenceElement); const documentRef = useRef(null); documentRef.current = containerDocument; const [dialogState, setDialogState] = useState(defaultDialogState); useSyncDialogState(dialogState, props.dispatch); useWindowCommands({ documentRef, customCss: props.customCss, plugins: props.plugins, editorNoteStatuses: props.editorNoteStatuses, setDialogState, }); useSyncActiveWindow(containerDocument?.defaultView); const onDialogHideCallbacks = useMemo(() => { type OnHideCallbacks = Partial void>>; const result: OnHideCallbacks = {}; for (const key of Object.keys(defaultDialogState)) { result[key as keyof DialogState] = () => { setDialogState(dialogState => { return { ...dialogState, [key]: { visible: false }, }; }); }; } return result; }, []); const promptOnClose = useCallback((answer: unknown, buttonType: unknown) => { dialogState.promptOptions.onClose(answer, buttonType); }, [dialogState.promptOptions]); const dialogInfo = PluginManager.instance().pluginDialogToShow(props.pluginsLegacy); const pluginDialog = !dialogInfo ? null : ; const { noteContentPropertiesDialogOptions, notePropertiesDialogOptions, shareNoteDialogOptions, shareFolderDialogOptions, promptOptions } = dialogState; return <>
{pluginDialog} {props.modalMessage !== null ? : null} {noteContentPropertiesDialogOptions.visible && ( )} {notePropertiesDialogOptions.visible && ( )} {shareNoteDialogOptions.visible && ( )} {shareFolderDialogOptions.visible && ( )} ; }; interface ConnectProps { windowId: string; } export default connect((state: AppState, ownProps: ConnectProps) => { const windowState = stateUtils.windowStateById(state, ownProps.windowId); return { themeId: state.settings.theme, plugins: state.pluginService.plugins, visibleDialogs: windowState.visibleDialogs, appDialogStates: windowState.dialogs, pluginHtmlContents: state.pluginService.pluginHtmlContents, customCss: state.customViewerCss, editorNoteStatuses: state.editorNoteStatuses, pluginsLegacy: state.pluginsLegacy, modalMessage: state.modalOverlayMessage, }; })(WindowCommandsAndDialogs);