diff --git a/app/components/DocumentMetaWithViews.tsx b/app/components/DocumentMetaWithViews.tsx index 4c6e0d044c..35dde5e622 100644 --- a/app/components/DocumentMetaWithViews.tsx +++ b/app/components/DocumentMetaWithViews.tsx @@ -2,13 +2,12 @@ import { LocationDescriptor } from "history"; import { observer, useObserver } from "mobx-react"; import * as React from "react"; import { useTranslation } from "react-i18next"; -import { usePopoverState, PopoverDisclosure } from "reakit/Popover"; +import { Link, useRouteMatch } from "react-router-dom"; import styled from "styled-components"; import Document from "~/models/Document"; import DocumentMeta from "~/components/DocumentMeta"; -import DocumentViews from "~/components/DocumentViews"; -import Popover from "~/components/Popover"; import useStores from "~/hooks/useStores"; +import { documentUrl, documentInsightsUrl } from "~/utils/routeHelpers"; import Fade from "./Fade"; type Props = { @@ -21,41 +20,32 @@ type Props = { function DocumentMetaWithViews({ to, isDraft, document, ...rest }: Props) { const { views } = useStores(); const { t } = useTranslation(); + const match = useRouteMatch(); const documentViews = useObserver(() => views.inDocument(document.id)); const totalViewers = documentViews.length; const onlyYou = totalViewers === 1 && documentViews[0].user.id; const viewsLoadedOnMount = React.useRef(totalViewers > 0); - const popover = usePopoverState({ - gutter: 8, - placement: "bottom", - modal: true, - }); - + const insightsUrl = documentInsightsUrl(document); const Wrapper = viewsLoadedOnMount.current ? React.Fragment : Fade; return ( {totalViewers && !isDraft ? ( - - {(props) => ( - -  •  - - {t("Viewed by")}{" "} - {onlyYou - ? t("only you") - : `${totalViewers} ${ - totalViewers === 1 ? t("person") : t("people") - }`} - - - )} - + +  •  + + {t("Viewed by")}{" "} + {onlyYou + ? t("only you") + : `${totalViewers} ${ + totalViewers === 1 ? t("person") : t("people") + }`} + + ) : null} - - - ); } diff --git a/app/hooks/useTextSelection.ts b/app/hooks/useTextSelection.ts index 85ec0ebe35..df2d6686ca 100644 --- a/app/hooks/useTextSelection.ts +++ b/app/hooks/useTextSelection.ts @@ -9,14 +9,15 @@ import useEventListener from "./useEventListener"; export default function useTextSelection() { const [selection, setSelection] = React.useState(""); - const handleMouse = React.useCallback(() => { - const selection = window.getSelection(); - const text = selection?.toString(); - setSelection(text ?? ""); - }, []); - - useEventListener("mousemove", handleMouse); - useEventListener("mouseup", handleMouse); + useEventListener( + "selectionchange", + () => { + const selection = window.getSelection(); + const text = selection?.toString(); + setSelection(text ?? ""); + }, + document + ); return selection; } diff --git a/app/scenes/Document/components/Insights.tsx b/app/scenes/Document/components/Insights.tsx index 77ae8a5520..bbbc65a70e 100644 --- a/app/scenes/Document/components/Insights.tsx +++ b/app/scenes/Document/components/Insights.tsx @@ -47,11 +47,13 @@ function Insights() { {t("Stats")} -
  • - {t(`{{ count }} minute read`, { - count: stats.total.readingTime, - })} -
  • + {stats.total.words > 0 && ( +
  • + {t(`{{ count }} minute read`, { + count: stats.total.readingTime, + })} +
  • + )}
  • {t(`{{ count }} words`, { count: stats.total.words })}
  • {t(`{{ count }} characters`, { @@ -80,24 +82,6 @@ function Insights() { - - {t("Views")} - - {documentViews.length <= 1 - ? t("No one else has viewed yet") - : t(`Viewed {{ count }} times by {{ teamMembers }} people`, { - count: documentViews.reduce( - (memo, view) => memo + view.count, - 0 - ), - teamMembers: documentViews.length, - })} - . - - - - - {t("Collaborators")} @@ -129,6 +113,26 @@ function Insights() { /> + + {t("Views")} + + {documentViews.length <= 1 + ? t("No one else has viewed yet") + : t(`Viewed {{ count }} times by {{ teamMembers }} people`, { + count: documentViews.reduce( + (memo, view) => memo + view.count, + 0 + ), + teamMembers: documentViews.length, + })} + . + + {documentViews.length > 1 && ( + + + + )} + ) : null} @@ -145,7 +149,7 @@ function useTextStats(text: string, selectedText: string) { words: numTotalWords, characters: text.length, emoji: matches.length ?? 0, - readingTime: Math.floor(numTotalWords / 200), + readingTime: Math.max(1, Math.floor(numTotalWords / 200)), }, selected: { words: countWords(selectedText), @@ -176,7 +180,7 @@ const List = styled("ul")` display: inline-block; font-weight: 600; color: ${(props) => props.theme.textTertiary}; - width: 8px; + width: 10px; } `; diff --git a/app/scenes/Document/components/RightSidebar.tsx b/app/scenes/Document/components/RightSidebar.tsx index cafd35cfed..41628d0a8e 100644 --- a/app/scenes/Document/components/RightSidebar.tsx +++ b/app/scenes/Document/components/RightSidebar.tsx @@ -2,12 +2,14 @@ import { m } from "framer-motion"; import { observer } from "mobx-react"; import { BackIcon } from "outline-icons"; import * as React from "react"; +import { useTranslation } from "react-i18next"; import styled, { useTheme } from "styled-components"; import breakpoint from "styled-components-breakpoint"; import Button from "~/components/Button"; import Flex from "~/components/Flex"; import Scrollable from "~/components/Scrollable"; import ResizeBorder from "~/components/Sidebar/components/ResizeBorder"; +import Tooltip from "~/components/Tooltip"; import usePersistedState from "~/hooks/usePersistedState"; type Props = React.HTMLAttributes & { @@ -19,6 +21,7 @@ type Props = React.HTMLAttributes & { function RightSidebar({ title, onClose, children, border, className }: Props) { const theme = useTheme(); + const { t } = useTranslation(); const [width, setWidth] = usePersistedState( "rightSidebarWidth", theme.sidebarWidth @@ -100,12 +103,14 @@ function RightSidebar({ title, onClose, children, border, className }: Props) {
    {title} -
    {children} unless restored.": "This template will be permanently deleted in <2> unless restored.", @@ -465,6 +465,7 @@ "Deleted by {{userName}}": "Deleted by {{userName}}", "Observing {{ userName }}": "Observing {{ userName }}", "Backlinks": "Backlinks", + "Close": "Close", "Anyone with the link <1>can view this document": "Anyone with the link <1>can view this document", "Share": "Share", "Share this document": "Share this document",