import { observer } from "mobx-react"; import { TableOfContentsIcon, EditIcon, PlusIcon, MoonIcon, MoreIcon, SunIcon, } from "outline-icons"; import * as React from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import styled from "styled-components"; import { Theme } from "~/stores/UiStore"; import Document from "~/models/Document"; import { Action, Separator } from "~/components/Actions"; import Badge from "~/components/Badge"; import Button from "~/components/Button"; import Collaborators from "~/components/Collaborators"; import DocumentBreadcrumb from "~/components/DocumentBreadcrumb"; import Header from "~/components/Header"; import Tooltip from "~/components/Tooltip"; import useMobile from "~/hooks/useMobile"; import useMouseMove from "~/hooks/useMouseMove"; import usePolicy from "~/hooks/usePolicy"; import useStores from "~/hooks/useStores"; import DocumentMenu from "~/menus/DocumentMenu"; import NewChildDocumentMenu from "~/menus/NewChildDocumentMenu"; import TableOfContentsMenu from "~/menus/TableOfContentsMenu"; import TemplatesMenu from "~/menus/TemplatesMenu"; import { NavigationNode } from "~/types"; import { metaDisplay } from "~/utils/keyboard"; import { newDocumentPath, editDocumentUrl } from "~/utils/routeHelpers"; import FadeOut from "./FadeOut"; import ObservingBanner from "./ObservingBanner"; import PublicBreadcrumb from "./PublicBreadcrumb"; import ShareButton from "./ShareButton"; type Props = { document: Document; documentHasHeadings: boolean; sharedTree: NavigationNode | undefined; shareId: string | null | undefined; isDraft: boolean; isEditing: boolean; isFocusing: boolean; isRevision: boolean; isSaving: boolean; isPublishing: boolean; publishingIsDisabled: boolean; savingIsDisabled: boolean; onSelectTemplate: (template: Document) => void; onSave: (options: { done?: boolean; publish?: boolean; autosave?: boolean; }) => void; headings: { title: string; level: number; id: string; }[]; }; function DocumentHeader({ document, documentHasHeadings, shareId, isEditing, isDraft, isPublishing, isRevision, isFocusing, isSaving, savingIsDisabled, publishingIsDisabled, sharedTree, onSelectTemplate, onSave, headings, }: Props) { const { t } = useTranslation(); const { ui, auth } = useStores(); const { resolvedTheme } = ui; const { team } = auth; const isMobile = useMobile(); const isMouseMoving = useMouseMove(); const hideHeader = isFocusing && !isMouseMoving; // We cache this value for as long as the component is mounted so that if you // apply a template there is still the option to replace it until the user // navigates away from the doc const [isNew] = React.useState(document.isPersistedOnce); const handleSave = React.useCallback(() => { onSave({ done: true, }); }, [onSave]); const handlePublish = React.useCallback(() => { onSave({ done: true, publish: true, }); }, [onSave]); const { isDeleted, isTemplate } = document; const can = usePolicy(document.id); const canToggleEmbeds = team?.documentEmbeds; const canEdit = can.update && !isEditing; const toc = ( ); const appearanceAction = ( ), [t] ); if (shareId) { return (
) : ( {documentHasHeadings ? toc : null} ) } actions={ <> {appearanceAction} {canEdit ? editAction :
} } /> ); } return ( <>
{isMobile ? ( ) : ( {!isEditing && toc} )} } title={ <> {document.title}{" "} {document.isArchived && {t("Archived")}} } actions={ <> {!isPublishing && isSaving && !team?.collaborativeEditing && ( {t("Saving")}… )} {!isDeleted && } {(isEditing || team?.collaborativeEditing) && !isTemplate && isNew && ( )} {!isEditing && !isDeleted && (!isMobile || !isTemplate) && ( )} {isEditing && ( <> )} {canEdit && !team?.collaborativeEditing && editAction} {canEdit && can.createChildDocument && !isMobile && ( )} {canEdit && isTemplate && !isDraft && !isRevision && ( )} {can.update && isDraft && !isRevision && ( )} {!isEditing && ( <> {!isDeleted && } )} } /> ); } const Status = styled(Action)` padding-left: 0; padding-right: 4px; color: ${(props) => props.theme.slate}; `; export default observer(DocumentHeader);