Revert "fix: Fade out navigation when editing and mouse hasn't moved (#3256)" (#3502)

This reverts commit e0cf873a36.
This commit is contained in:
Tom Moor
2022-05-06 13:28:37 -07:00
committed by GitHub
parent e0cf873a36
commit b75a6928cb
9 changed files with 158 additions and 240 deletions

View File

@@ -83,4 +83,4 @@ const Meta = styled(DocumentMeta)<{ rtl?: boolean }>`
} }
`; `;
export default React.memo(DocumentMetaWithViews); export default DocumentMetaWithViews;

View File

@@ -21,7 +21,7 @@ const searcher = new FuzzySearch<{
sort: true, sort: true,
}); });
class EmojiMenu extends React.PureComponent< class EmojiMenu extends React.Component<
Omit< Omit<
Props<Emoji>, Props<Emoji>,
| "renderMenuItem" | "renderMenuItem"

View File

@@ -1,28 +0,0 @@
import * as React from "react";
/**
* Hook to check if mouse is moving in the window
* @param {number} [timeout] - time in ms to wait before marking the mouse as not moving
* @returns {boolean} true if the mouse is moving, false otherwise
*/
const useMouseMove = (timeout = 5000) => {
const [isMouseMoving, setIsMouseMoving] = React.useState(false);
const timeoutId = React.useRef<ReturnType<typeof setTimeout>>();
const onMouseMove = React.useCallback(() => {
timeoutId.current && clearTimeout(timeoutId.current);
setIsMouseMoving(true);
timeoutId.current = setTimeout(() => setIsMouseMoving(false), timeout);
}, [timeout]);
React.useEffect(() => {
document.addEventListener("mousemove", onMouseMove);
return () => {
document.removeEventListener("mousemove", onMouseMove);
};
}, [onMouseMove]);
return isMouseMoving;
};
export default useMouseMove;

View File

@@ -5,7 +5,7 @@ import parseTitle from "@shared/utils/parseTitle";
import unescape from "@shared/utils/unescape"; import unescape from "@shared/utils/unescape";
import DocumentsStore from "~/stores/DocumentsStore"; import DocumentsStore from "~/stores/DocumentsStore";
import User from "~/models/User"; import User from "~/models/User";
import type { NavigationNode } from "~/types"; import { NavigationNode } from "~/types";
import Storage from "~/utils/Storage"; import Storage from "~/utils/Storage";
import ParanoidModel from "./ParanoidModel"; import ParanoidModel from "./ParanoidModel";
import View from "./View"; import View from "./View";

View File

@@ -87,9 +87,6 @@ class DocumentScene extends React.Component<Props> {
@observable @observable
isEditorDirty = false; isEditorDirty = false;
@observable
isEditorFocused = false;
@observable @observable
isEmpty = true; isEmpty = true;
@@ -415,9 +412,6 @@ class DocumentScene extends React.Component<Props> {
} }
}; };
onBlur = () => (this.isEditorFocused = false);
onFocus = () => (this.isEditorFocused = true);
render() { render() {
const { const {
document, document,
@@ -455,9 +449,6 @@ class DocumentScene extends React.Component<Props> {
? this.props.match.url ? this.props.match.url
: updateDocumentUrl(this.props.match.url, document); : updateDocumentUrl(this.props.match.url, document);
const isFocusing =
!readOnly || this.isEditorFocused || !!ui.observingUserId;
return ( return (
<ErrorBoundary> <ErrorBoundary>
{this.props.location.pathname !== canonicalUrl && ( {this.props.location.pathname !== canonicalUrl && (
@@ -547,7 +538,6 @@ class DocumentScene extends React.Component<Props> {
shareId={shareId} shareId={shareId}
isRevision={!!revision} isRevision={!!revision}
isDraft={document.isDraft} isDraft={document.isDraft}
isFocusing={isFocusing}
isEditing={!readOnly && !team?.collaborativeEditing} isEditing={!readOnly && !team?.collaborativeEditing}
isSaving={this.isSaving} isSaving={this.isSaving}
isPublishing={this.isPublishing} isPublishing={this.isPublishing}
@@ -589,8 +579,6 @@ class DocumentScene extends React.Component<Props> {
document={document} document={document}
value={readOnly ? value : undefined} value={readOnly ? value : undefined}
defaultValue={value} defaultValue={value}
onBlur={this.onBlur}
onFocus={this.onFocus}
embedsDisabled={embedsDisabled} embedsDisabled={embedsDisabled}
onSynced={this.onSynced} onSynced={this.onSynced}
onFileUploadStart={this.onFileUploadStart} onFileUploadStart={this.onFileUploadStart}
@@ -618,10 +606,7 @@ class DocumentScene extends React.Component<Props> {
<> <>
<MarkAsViewed document={document} /> <MarkAsViewed document={document} />
<ReferencesWrapper isOnlyTitle={document.isOnlyTitle}> <ReferencesWrapper isOnlyTitle={document.isOnlyTitle}>
<References <References document={document} />
isFocusing={isFocusing}
document={document}
/>
</ReferencesWrapper> </ReferencesWrapper>
</> </>
)} )}

View File

@@ -1,11 +0,0 @@
import * as React from "react";
import styled from "styled-components";
import Flex from "~/components/Flex";
const FadeOut = styled(Flex)<{ $fade: boolean }>`
opacity: ${(props) => (props.$fade ? 0 : 1)};
visibility: ${(props) => (props.$fade ? "hidden" : "visible")};
transition: opacity 900ms ease-in-out, visibility ease-in-out 900ms;
`;
export default React.memo(FadeOut);

View File

@@ -21,7 +21,6 @@ import DocumentBreadcrumb from "~/components/DocumentBreadcrumb";
import Header from "~/components/Header"; import Header from "~/components/Header";
import Tooltip from "~/components/Tooltip"; import Tooltip from "~/components/Tooltip";
import useMobile from "~/hooks/useMobile"; import useMobile from "~/hooks/useMobile";
import useMouseMove from "~/hooks/useMouseMove";
import usePolicy from "~/hooks/usePolicy"; import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import DocumentMenu from "~/menus/DocumentMenu"; import DocumentMenu from "~/menus/DocumentMenu";
@@ -31,7 +30,6 @@ import TemplatesMenu from "~/menus/TemplatesMenu";
import { NavigationNode } from "~/types"; import { NavigationNode } from "~/types";
import { metaDisplay } from "~/utils/keyboard"; import { metaDisplay } from "~/utils/keyboard";
import { newDocumentPath, editDocumentUrl } from "~/utils/routeHelpers"; import { newDocumentPath, editDocumentUrl } from "~/utils/routeHelpers";
import FadeOut from "./FadeOut";
import ObservingBanner from "./ObservingBanner"; import ObservingBanner from "./ObservingBanner";
import PublicBreadcrumb from "./PublicBreadcrumb"; import PublicBreadcrumb from "./PublicBreadcrumb";
import ShareButton from "./ShareButton"; import ShareButton from "./ShareButton";
@@ -43,7 +41,6 @@ type Props = {
shareId: string | null | undefined; shareId: string | null | undefined;
isDraft: boolean; isDraft: boolean;
isEditing: boolean; isEditing: boolean;
isFocusing: boolean;
isRevision: boolean; isRevision: boolean;
isSaving: boolean; isSaving: boolean;
isPublishing: boolean; isPublishing: boolean;
@@ -70,7 +67,6 @@ function DocumentHeader({
isDraft, isDraft,
isPublishing, isPublishing,
isRevision, isRevision,
isFocusing,
isSaving, isSaving,
savingIsDisabled, savingIsDisabled,
publishingIsDisabled, publishingIsDisabled,
@@ -84,8 +80,6 @@ function DocumentHeader({
const { resolvedTheme } = ui; const { resolvedTheme } = ui;
const { team } = auth; const { team } = auth;
const isMobile = useMobile(); 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 // 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 // apply a template there is still the option to replace it until the user
@@ -169,35 +163,6 @@ function DocumentHeader({
</Action> </Action>
); );
const DocumentMenuLabel = React.useCallback(
(props) => (
<Button
icon={<MoreIcon />}
iconColor="currentColor"
{...props}
borderOnHover
neutral
/>
),
[]
);
const NewChildDocLabel = React.useCallback(
(props) => (
<Tooltip
tooltip={t("New document")}
shortcut="n"
delay={500}
placement="bottom"
>
<Button icon={<PlusIcon />} {...props} neutral>
{t("New doc")}
</Button>
</Tooltip>
),
[t]
);
if (shareId) { if (shareId) {
return ( return (
<Header <Header
@@ -231,15 +196,13 @@ function DocumentHeader({
<Header <Header
hasSidebar hasSidebar
breadcrumb={ breadcrumb={
<FadeOut $fade={hideHeader}> isMobile ? (
{isMobile ? ( <TableOfContentsMenu headings={headings} />
<TableOfContentsMenu headings={headings} /> ) : (
) : ( <DocumentBreadcrumb document={document}>
<DocumentBreadcrumb document={document}> {!isEditing && toc}
{!isEditing && toc} </DocumentBreadcrumb>
</DocumentBreadcrumb> )
)}
</FadeOut>
} }
title={ title={
<> <>
@@ -250,101 +213,117 @@ function DocumentHeader({
actions={ actions={
<> <>
<ObservingBanner /> <ObservingBanner />
<FadeOut $fade={hideHeader}>
{!isPublishing && isSaving && !team?.collaborativeEditing && ( {!isPublishing && isSaving && !team?.collaborativeEditing && (
<Status>{t("Saving")}</Status> <Status>{t("Saving")}</Status>
)} )}
{!isDeleted && <Collaborators document={document} />} {!isDeleted && <Collaborators document={document} />}
{(isEditing || team?.collaborativeEditing) && {(isEditing || team?.collaborativeEditing) && !isTemplate && isNew && (
!isTemplate && <Action>
isNew && ( <TemplatesMenu
<Action> document={document}
<TemplatesMenu onSelectTemplate={onSelectTemplate}
document={document} />
onSelectTemplate={onSelectTemplate} </Action>
/> )}
</Action> {!isEditing && !isDeleted && (!isMobile || !isTemplate) && (
)} <Action>
{!isEditing && !isDeleted && (!isMobile || !isTemplate) && ( <ShareButton document={document} />
<Action> </Action>
<ShareButton document={document} /> )}
</Action> {isEditing && (
)} <>
{isEditing && (
<>
<Action>
<Tooltip
tooltip={t("Save")}
shortcut={`${metaDisplay}+enter`}
delay={500}
placement="bottom"
>
<Button
onClick={handleSave}
disabled={savingIsDisabled}
neutral={isDraft}
>
{isDraft ? t("Save Draft") : t("Done Editing")}
</Button>
</Tooltip>
</Action>
</>
)}
{canEdit && !team?.collaborativeEditing && editAction}
{canEdit && can.createChildDocument && !isMobile && (
<Action>
<NewChildDocumentMenu
document={document}
label={NewChildDocLabel}
/>
</Action>
)}
{canEdit && isTemplate && !isDraft && !isRevision && (
<Action>
<Button
icon={<PlusIcon />}
as={Link}
to={newDocumentPath(document.collectionId, {
templateId: document.id,
})}
primary
>
{t("New from template")}
</Button>
</Action>
)}
{can.update && isDraft && !isRevision && (
<Action> <Action>
<Tooltip <Tooltip
tooltip={t("Publish")} tooltip={t("Save")}
shortcut={`${metaDisplay}+shift+p`} shortcut={`${metaDisplay}+enter`}
delay={500} delay={500}
placement="bottom" placement="bottom"
> >
<Button <Button
onClick={handlePublish} onClick={handleSave}
disabled={publishingIsDisabled} disabled={savingIsDisabled}
neutral={isDraft}
> >
{isPublishing ? `${t("Publishing")}` : t("Publish")} {isDraft ? t("Save Draft") : t("Done Editing")}
</Button> </Button>
</Tooltip> </Tooltip>
</Action> </Action>
)} </>
{!isEditing && ( )}
<> {canEdit && !team?.collaborativeEditing && editAction}
{!isDeleted && <Separator />} {canEdit && can.createChildDocument && !isMobile && (
<Action> <Action>
<DocumentMenu <NewChildDocumentMenu
document={document} document={document}
isRevision={isRevision} label={(props) => (
label={DocumentMenuLabel} <Tooltip
showToggleEmbeds={canToggleEmbeds} tooltip={t("New document")}
showDisplayOptions shortcut="n"
/> delay={500}
</Action> placement="bottom"
</> >
)} <Button icon={<PlusIcon />} {...props} neutral>
</FadeOut> {t("New doc")}
</Button>
</Tooltip>
)}
/>
</Action>
)}
{canEdit && isTemplate && !isDraft && !isRevision && (
<Action>
<Button
icon={<PlusIcon />}
as={Link}
to={newDocumentPath(document.collectionId, {
templateId: document.id,
})}
primary
>
{t("New from template")}
</Button>
</Action>
)}
{can.update && isDraft && !isRevision && (
<Action>
<Tooltip
tooltip={t("Publish")}
shortcut={`${metaDisplay}+shift+p`}
delay={500}
placement="bottom"
>
<Button
onClick={handlePublish}
disabled={publishingIsDisabled}
>
{isPublishing ? `${t("Publishing")}` : t("Publish")}
</Button>
</Tooltip>
</Action>
)}
{!isEditing && (
<>
{!isDeleted && <Separator />}
<Action>
<DocumentMenu
document={document}
isRevision={isRevision}
label={(props) => (
<Button
icon={<MoreIcon />}
iconColor="currentColor"
{...props}
borderOnHover
neutral
/>
)}
showToggleEmbeds={canToggleEmbeds}
showDisplayOptions
/>
</Action>
</>
)}
</> </>
} }
/> />

View File

@@ -7,21 +7,16 @@ import Document from "~/models/Document";
import Fade from "~/components/Fade"; import Fade from "~/components/Fade";
import Tab from "~/components/Tab"; import Tab from "~/components/Tab";
import Tabs from "~/components/Tabs"; import Tabs from "~/components/Tabs";
import useMouseMove from "~/hooks/useMouseMove";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import FadeOut from "./FadeOut";
import ReferenceListItem from "./ReferenceListItem"; import ReferenceListItem from "./ReferenceListItem";
type Props = { type Props = {
document: Document; document: Document;
isFocusing: boolean;
}; };
function References({ document, isFocusing }: Props) { function References({ document }: Props) {
const { collections, documents } = useStores(); const { collections, documents } = useStores();
const location = useLocation(); const location = useLocation();
const isMouseMoving = useMouseMove();
const hideHeader = isFocusing && !isMouseMoving;
React.useEffect(() => { React.useEffect(() => {
documents.fetchBacklinks(document.id); documents.fetchBacklinks(document.id);
@@ -38,54 +33,52 @@ function References({ document, isFocusing }: Props) {
const height = Math.max(backlinks.length, children.length) * 40; const height = Math.max(backlinks.length, children.length) * 40;
return showBacklinks || showChildDocuments ? ( return showBacklinks || showChildDocuments ? (
<FadeOut $fade={hideHeader}> <Fade>
<Fade style={{ width: "100%" }}> <Tabs>
<Tabs> {showChildDocuments && (
{showChildDocuments && ( <Tab to="#children" isActive={() => !isBacklinksTab}>
<Tab to="#children" isActive={() => !isBacklinksTab}> <Trans>Nested documents</Trans>
<Trans>Nested documents</Trans> </Tab>
</Tab> )}
)} {showBacklinks && (
{showBacklinks && ( <Tab to="#backlinks" isActive={() => isBacklinksTab}>
<Tab to="#backlinks" isActive={() => isBacklinksTab}> <Trans>Backlinks</Trans>
<Trans>Backlinks</Trans> </Tab>
</Tab> )}
)} </Tabs>
</Tabs> <Content style={{ height }}>
<Content style={{ height }}> {showBacklinks && (
{showBacklinks && ( <List $active={isBacklinksTab}>
<List $active={isBacklinksTab}> {backlinks.map((backlinkedDocument) => (
{backlinks.map((backlinkedDocument) => ( <ReferenceListItem
anchor={document.urlId}
key={backlinkedDocument.id}
document={backlinkedDocument}
showCollection={
backlinkedDocument.collectionId !== document.collectionId
}
/>
))}
</List>
)}
{showChildDocuments && (
<List $active={!isBacklinksTab}>
{children.map((node) => {
// If we have the document in the store already then use it to get the extra
// contextual info, otherwise the collection node will do (only has title and id)
const document = documents.get(node.id);
return (
<ReferenceListItem <ReferenceListItem
anchor={document.urlId} key={node.id}
key={backlinkedDocument.id} document={document || node}
document={backlinkedDocument} showCollection={false}
showCollection={
backlinkedDocument.collectionId !== document.collectionId
}
/> />
))} );
</List> })}
)} </List>
{showChildDocuments && ( )}
<List $active={!isBacklinksTab}> </Content>
{children.map((node) => { </Fade>
// If we have the document in the store already then use it to get the extra
// contextual info, otherwise the collection node will do (only has title and id)
const document = documents.get(node.id);
return (
<ReferenceListItem
key={node.id}
document={document || node}
showCollection={false}
/>
);
})}
</List>
)}
</Content>
</Fade>
</FadeOut>
) : null; ) : null;
} }

View File

@@ -445,4 +445,4 @@ const Label = styled.dd`
color: ${(props) => props.theme.textSecondary}; color: ${(props) => props.theme.textSecondary};
`; `;
export default React.memo(KeyboardShortcuts); export default KeyboardShortcuts;