import React, { useCallback, useEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { Input, Popover, PopoverBody } from 'reactstrap'; import classnames from 'classnames'; import data from '@emoji-mart/data'; import Picker from '@emoji-mart/react'; import { init } from 'emoji-mart'; import { gettext } from '../../../utils/constants'; import { WIKI_COVER_LIST } from '../constant'; // init data for emoji-mart, used in Picker and `getRandomEmoji` method init({ data }); const propTypes = { currentPageConfig: PropTypes.object.isRequired, onUpdatePage: PropTypes.func.isRequired, }; const PageHeader = ({ currentPageConfig, onUpdatePage }) => { const [isShowController, setIsShowController] = useState(false); const [isShowIconPanel, setIsShowIconPanel] = useState(false); const [isShowCoverController, setIsShowCoverController] = useState(false); const [isShowCoverPanel, setIsShowCoverPanel] = useState(false); const iconPanelPopoverRef = useRef(null); const coverPanelPopoverRef = useRef(null); const headerWrapperRef = useRef(null); const getCoverImgUrl = useCallback((imageName) => { const { serviceUrl, mediaUrl } = window.seafile; return `${serviceUrl}${mediaUrl}img/wiki/cover/${imageName}`; }, []); const handleRenameDocument = useCallback((e) => { const { nativeEvent: { isComposing } } = e; if (isComposing) return; const newName = e.target.value.trim(); const { id, name, icon } = currentPageConfig; if (newName === name) return; const pageConfig = { name: newName, icon }; onUpdatePage && onUpdatePage(id, pageConfig); }, [currentPageConfig, onUpdatePage]); const changeControllerDisplayed = useCallback((isShowController) => { if (isShowCoverPanel) return; setIsShowController(isShowController); }, [isShowCoverPanel]); const handleSetIcon = useCallback((emoji, cb) => { onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: emoji }); cb && cb(); }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); const setRandomEmoji = useCallback(() => { const nativeEmojis = Reflect.ownKeys(data.natives); const emojiCount = nativeEmojis.length; const emoji = nativeEmojis[Math.floor(Math.random() * emojiCount)]; handleSetIcon(emoji); }, [handleSetIcon]); const handleIconPanelDisplayedChange = useCallback((isShowIconPanel) => { setIsShowIconPanel(isShowIconPanel); setIsShowCoverPanel(false); }, []); const handleClickAddIcon = useCallback(() => { setRandomEmoji(); handleIconPanelDisplayedChange(false); }, [handleIconPanelDisplayedChange, setRandomEmoji]); const handleIconPanelListener = useCallback((e) => { const isClickInPopover = iconPanelPopoverRef.current.contains(e.target); if (!isClickInPopover) handleIconPanelDisplayedChange(false); }, [handleIconPanelDisplayedChange]); const handleCoverPanelDisplayedChange = useCallback((isShowCoverPanel) => { setIsShowCoverPanel(isShowCoverPanel); setIsShowIconPanel(false); }, []); const handleCoverPanelListener = useCallback((e) => { const isClickInPopover = coverPanelPopoverRef.current.contains(e.target); if (!isClickInPopover) handleCoverPanelDisplayedChange(false); }, [handleCoverPanelDisplayedChange]); // Update current page favicon useEffect(() => { let faviconUrl = ''; if (currentPageConfig.icon) { faviconUrl = `data:image/svg+xml,${currentPageConfig.icon}`; } else { const { serviceUrl, mediaUrl, faviconPath } = window.seafile; faviconUrl = `${serviceUrl}${mediaUrl}${faviconPath}`; } document.getElementById('favicon').href = faviconUrl; }, [currentPageConfig.icon]); useEffect(() => { if (isShowIconPanel) { setTimeout(() => { // Avoid open behavior closing popover addEventListener('click', handleIconPanelListener); }, 0); } if (!isShowIconPanel) removeEventListener('click', handleIconPanelListener); if (isShowCoverPanel) { setTimeout(() => { // Avoid open behavior closing popover addEventListener('click', handleCoverPanelListener); }, 0); } if (!isShowCoverPanel) removeEventListener('click', handleCoverPanelListener); return () => { removeEventListener('click', handleIconPanelListener); removeEventListener('click', handleCoverPanelListener); }; }, [handleCoverPanelListener, handleIconPanelListener, isShowCoverPanel, isShowIconPanel]); const handleIconRemove = () => { handleSetIcon(''); handleIconPanelDisplayedChange(false); }; const handleAddCover = useCallback(() => { const coverName = WIKI_COVER_LIST[Math.floor(Math.random() * WIKI_COVER_LIST.length)]; const coverImgUrl = `${coverName}`; onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: coverImgUrl }); }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); const showCoverController = useCallback(() => { setIsShowCoverController(true); }, []); const hideCoverController = useCallback((e) => { if (isShowCoverPanel) return; setIsShowCoverController(false); }, [isShowCoverPanel]); const handleSetCoverImage = (coverName) => { const coverImgUrl = `${coverName}`; onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: coverImgUrl }); handleCoverPanelDisplayedChange(false); }; const handleCoverRemove = () => { onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: '' }); handleCoverPanelDisplayedChange(false); }; return (
{currentPageConfig.cover_img_url && (
{gettext('Cover')} {isShowCoverController && (
{gettext('Change cover')}
void 0} placement="bottom" isOpen={!!(isShowCoverPanel && currentPageConfig.cover_img_url)} innerClassName='wiki-cover-panel' hideArrow={true} popperClassName='wiki-cover-popover' >
{gettext('Gallery')} {gettext('Remove')}
{ WIKI_COVER_LIST.map(imgName => ( {gettext('Cover')} )) }
)}
)}
{currentPageConfig.icon}
void 0} placement="bottom" isOpen={!!(isShowIconPanel && !!currentPageConfig.icon)} popperClassName='wiki-icon-popover' hideArrow={true} >
{gettext('Emojis')} {gettext('Remove')}
handleSetIcon(emoji.native, handleIconPanelDisplayedChange.bind(null, false))} previewPosition="none" skinTonePosition="none" locale={window.seafile.lang.slice(0, 2)} maxFrequentRows={2} theme="light" />
{!currentPageConfig.icon && (
{gettext('Add icon')}
)} {!currentPageConfig.cover_img_url && (
{gettext('Add cover')}
)}
); }; PageHeader.propTypes = propTypes; export default PageHeader;