mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
fix: Improve scroll to comment logic, closes #7435
This commit is contained in:
@@ -11,7 +11,7 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import AutoSizer from "react-virtualized-auto-sizer";
|
||||
import { FixedSizeList as List } from "react-window";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled, { useTheme } from "styled-components";
|
||||
import breakpoint from "styled-components-breakpoint";
|
||||
import { NavigationNode } from "@shared/types";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled from "styled-components";
|
||||
import { ellipsis } from "@shared/styles";
|
||||
import { Node as SearchResult } from "~/components/DocumentExplorerNode";
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
} from "@getoutline/react-roving-tabindex";
|
||||
import { LocationDescriptor } from "history";
|
||||
import * as React from "react";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled, { useTheme } from "styled-components";
|
||||
import { s, ellipsis } from "@shared/styles";
|
||||
import Flex from "~/components/Flex";
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
match,
|
||||
} from "react-router";
|
||||
import { Link } from "react-router-dom";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import history from "~/utils/history";
|
||||
|
||||
const resolveToLocation = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import useQuery from "~/hooks/useQuery";
|
||||
import lazyWithRetry from "~/utils/lazyWithRetry";
|
||||
import type { Props } from "./Table";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled, { css } from "styled-components";
|
||||
import { s, ellipsis } from "@shared/styles";
|
||||
|
||||
@@ -22,7 +22,7 @@ function LinkSearchResult({
|
||||
const ref = React.useCallback(
|
||||
(node: HTMLElement | null) => {
|
||||
if (selected && node) {
|
||||
void scrollIntoView(node, {
|
||||
scrollIntoView(node, {
|
||||
scrollMode: "if-needed",
|
||||
block: "center",
|
||||
boundary: (parent) =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled from "styled-components";
|
||||
import MenuItem from "~/components/ContextMenu/MenuItem";
|
||||
import { usePortalContext } from "~/components/Portal";
|
||||
@@ -31,7 +31,7 @@ function SuggestionsMenuItem({
|
||||
const ref = React.useCallback(
|
||||
(node) => {
|
||||
if (selected && node) {
|
||||
void scrollIntoView(node, {
|
||||
scrollIntoView(node, {
|
||||
scrollMode: "if-needed",
|
||||
block: "nearest",
|
||||
boundary: (parent) =>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Node } from "prosemirror-model";
|
||||
import { Command, Plugin, PluginKey } from "prosemirror-state";
|
||||
import { Decoration, DecorationSet } from "prosemirror-view";
|
||||
import * as React from "react";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import Extension, { WidgetProps } from "@shared/editor/lib/Extension";
|
||||
import FindAndReplace from "../components/FindAndReplace";
|
||||
|
||||
@@ -184,7 +184,7 @@ export default class FindAndReplaceExtension extends Extension {
|
||||
`.${this.options.resultCurrentClassName}`
|
||||
);
|
||||
if (element) {
|
||||
void scrollIntoView(element, {
|
||||
scrollIntoView(element, {
|
||||
scrollMode: "if-needed",
|
||||
block: "center",
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import styled, { css } from "styled-components";
|
||||
import breakpoint from "styled-components-breakpoint";
|
||||
import { s } from "@shared/styles";
|
||||
@@ -64,6 +64,7 @@ function CommentThread({
|
||||
recessed,
|
||||
focused,
|
||||
}: Props) {
|
||||
const [focusedOnMount] = React.useState(focused);
|
||||
const { editor } = useDocumentContext();
|
||||
const { comments } = useStores();
|
||||
const topRef = React.useRef<HTMLDivElement>(null);
|
||||
@@ -103,7 +104,8 @@ function CommentThread({
|
||||
|
||||
const handleClickThread = () => {
|
||||
history.replace({
|
||||
search: location.search,
|
||||
// Clear any commentId from the URL when explicitly focusing a thread
|
||||
search: "",
|
||||
pathname: location.pathname.replace(/\/history$/, ""),
|
||||
state: { commentId: thread.id },
|
||||
});
|
||||
@@ -117,17 +119,26 @@ function CommentThread({
|
||||
|
||||
React.useEffect(() => {
|
||||
if (focused) {
|
||||
// If the thread is already visible, scroll it into view immediately,
|
||||
// otherwise wait for the sidebar to appear.
|
||||
const isThreadVisible =
|
||||
(topRef.current?.getBoundingClientRect().left ?? 0) < window.innerWidth;
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
if (focusedOnMount) {
|
||||
setTimeout(() => {
|
||||
if (!topRef.current) {
|
||||
return;
|
||||
}
|
||||
scrollIntoView(topRef.current, {
|
||||
scrollMode: "if-needed",
|
||||
behavior: "auto",
|
||||
block: "nearest",
|
||||
boundary: (parent) =>
|
||||
// Prevents body and other parent elements from being scrolled
|
||||
parent.id !== "comments",
|
||||
});
|
||||
}, sidebarAppearDuration);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (!replyRef.current) {
|
||||
return;
|
||||
}
|
||||
return scrollIntoView(replyRef.current, {
|
||||
scrollIntoView(replyRef.current, {
|
||||
scrollMode: "if-needed",
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
@@ -135,9 +146,8 @@ function CommentThread({
|
||||
// Prevents body and other parent elements from being scrolled
|
||||
parent.id !== "comments",
|
||||
});
|
||||
},
|
||||
isThreadVisible ? 0 : sidebarAppearDuration
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
const getCommentMarkElement = () =>
|
||||
window.document?.getElementById(`comment-${thread.id}`);
|
||||
@@ -153,7 +163,7 @@ function CommentThread({
|
||||
isMarkVisible ? 0 : sidebarAppearDuration
|
||||
);
|
||||
}
|
||||
}, [focused, thread.id]);
|
||||
}, [focused, focusedOnMount, thread.id]);
|
||||
|
||||
const [draft, onSaveDraft] = usePersistedState<ProsemirrorData | undefined>(
|
||||
`draft-${document.id}-${thread.id}`,
|
||||
|
||||
+1
-1
@@ -220,7 +220,7 @@
|
||||
"sequelize-typescript": "^2.1.6",
|
||||
"slug": "^5.3.0",
|
||||
"slugify": "^1.6.6",
|
||||
"smooth-scroll-into-view-if-needed": "^1.1.33",
|
||||
"scroll-into-view-if-needed": "^3.1.0",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"socket.io-redis": "^6.1.1",
|
||||
|
||||
@@ -6617,10 +6617,10 @@ compute-scroll-into-view@1.0.14:
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz#80e3ebb25d6aa89f42e533956cb4b16a04cfe759"
|
||||
integrity "sha1-gOPrsl1qqJ9C5TOVbLSxagTP51k= sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ=="
|
||||
|
||||
compute-scroll-into-view@^1.0.17:
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab"
|
||||
integrity "sha1-aojxis2dQunPS6pr7H4FImB6t6s= sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg=="
|
||||
compute-scroll-into-view@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz#753f11d972596558d8fe7c6bcbc8497690ab4c87"
|
||||
integrity sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
@@ -13608,12 +13608,12 @@ scheduler@^0.20.2:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scroll-into-view-if-needed@^2.2.28:
|
||||
version "2.2.28"
|
||||
resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.28.tgz#5a15b2f58a52642c88c8eca584644e01703d645a"
|
||||
integrity "sha1-WhWy9YpSZCyIyOylhGROAXA9ZFo= sha512-8LuxJSuFVc92+0AdNv4QOxRL4Abeo1DgLnGNkn1XlaujPH/3cCFz3QI60r2VNu4obJJROzgnIUw5TKQkZvZI1w=="
|
||||
scroll-into-view-if-needed@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz#fa9524518c799b45a2ef6bbffb92bcad0296d01f"
|
||||
integrity sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==
|
||||
dependencies:
|
||||
compute-scroll-into-view "^1.0.17"
|
||||
compute-scroll-into-view "^3.0.2"
|
||||
|
||||
selderee@^0.11.0:
|
||||
version "0.11.0"
|
||||
@@ -13832,13 +13832,6 @@ smob@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab"
|
||||
integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==
|
||||
|
||||
smooth-scroll-into-view-if-needed@^1.1.33:
|
||||
version "1.1.33"
|
||||
resolved "https://registry.yarnpkg.com/smooth-scroll-into-view-if-needed/-/smooth-scroll-into-view-if-needed-1.1.33.tgz#2c7b88c82784c69030cb0489b9df584e94e01533"
|
||||
integrity "sha1-LHuIyCeExpAwywSJud9YTpTgFTM= sha512-crS8NfAaoPrtVYOCMSAnO2vHRgUp22NiiDgEQ7YiaAy5xe2jmR19Jm+QdL8+97gO8ENd7PUyQIAQojJyIiyRHw=="
|
||||
dependencies:
|
||||
scroll-into-view-if-needed "^2.2.28"
|
||||
|
||||
socket.io-adapter@~2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.2.0.tgz#43af9157c4609e74b8addc6867873ac7eb48fda2"
|
||||
|
||||
Reference in New Issue
Block a user