import * as React from 'react'; import { useCallback, useState, useRef, useEffect, useId } from 'react'; import { _ } from '@joplin/lib/locale'; import DialogButtonRow, { ClickEvent } from '../DialogButtonRow'; import Dialog from '../Dialog'; import DialogTitle from '../DialogTitle'; import StyledInput from '../style/StyledInput'; import { IconSelector, ChangeEvent } from './IconSelector'; import useAsyncEffect, { AsyncEffectEvent } from '@joplin/lib/hooks/useAsyncEffect'; import Folder from '@joplin/lib/models/Folder'; import { FolderEntity, FolderIcon, FolderIconType } from '@joplin/lib/services/database/types'; import Button from '../Button/Button'; import bridge from '../../services/bridge'; import shim from '@joplin/lib/shim'; import FolderIconBox from '../FolderIconBox'; import { focus } from '@joplin/lib/utils/focusHandler'; interface Props { themeId: number; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied dispatch: Function; folderId: string; parentId: string; } export default function(props: Props) { const [folderTitle, setFolderTitle] = useState(''); const [folderIcon, setFolderIcon] = useState(); const titleInputRef = useRef(null); const isNew = !props.folderId; useAsyncEffect(async (event: AsyncEffectEvent) => { if (isNew) return; const folder = await Folder.load(props.folderId); if (event.cancelled) return; setFolderTitle(folder.title); setFolderIcon(Folder.unserializeIcon(folder.icon)); }, [props.folderId, isNew]); const onClose = useCallback(() => { props.dispatch({ type: 'DIALOG_CLOSE', name: 'editFolder', }); }, [props.dispatch]); useEffect(() => { focus('Dialog::titleInputRef', titleInputRef.current); setTimeout(() => { titleInputRef.current.select(); }, 100); }, []); const onButtonRowClick = useCallback(async (event: ClickEvent) => { if (event.buttonName === 'cancel') { onClose(); return; } if (event.buttonName === 'ok') { const folder: FolderEntity = { title: folderTitle, icon: Folder.serializeIcon(folderIcon), }; if (!isNew) folder.id = props.folderId; if (props.parentId) folder.parent_id = props.parentId; try { const savedFolder = await Folder.save(folder, { userSideValidation: true }); onClose(); props.dispatch({ type: 'FOLDER_SELECT', id: savedFolder.id, }); } catch (error) { bridge().showErrorMessageBox(error.message); } return; } // eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied }, [onClose, folderTitle, folderIcon, props.folderId, props.parentId]); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied const onFolderTitleChange = useCallback((event: any) => { setFolderTitle(event.target.value); }, []); const onFolderIconChange = useCallback((event: ChangeEvent) => { setFolderIcon(event.value); }, []); const onClearClick = useCallback(() => { setFolderIcon(null); }, []); const onBrowseClick = useCallback(async () => { const filePaths = await bridge().showOpenDialog({ filters: [ { name: _('Images'), extensions: ['jpg', 'jpeg', 'png'], }, ], }); if (filePaths.length !== 1) return; const filePath = filePaths[0]; try { const dataUrl = await shim.imageToDataUrl(filePath, 256); setFolderIcon(icon => { return { ...icon, emoji: '', name: '', type: FolderIconType.DataUrl, dataUrl, }; }); } catch (error) { await bridge().showErrorMessageBox(error.message); } }, []); const formTitleInputId = useId(); function renderForm() { return (
{ folderIcon &&
}
); } function renderContent() { return (
{renderForm()}
); } const dialogTitle = isNew ? _('Create notebook') : _('Edit notebook'); function renderDialogWrapper() { return (
{renderContent()}
); } return ( {renderDialogWrapper()} ); }