Skip to content

Commit

Permalink
fix: toolbar dom & memory leak
Browse files Browse the repository at this point in the history
  • Loading branch information
WindRunnerMax committed Jan 8, 2025
1 parent da5a1f5 commit a389b50
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 22 deletions.
33 changes: 18 additions & 15 deletions packages/plugin/src/float-toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { HYPER_LINK_KEY } from "../hyper-link/types";
import { LINE_HEIGHT_KEY } from "../line-height/types";
import { useMemoFn } from "../shared/hooks/preset";
import { MenuItems } from "./components/menu";
import { execSelectMarks, getSelectionRect, maskMenuToolBar, Portal } from "./utils/selection";
import { execSelectMarks, getSelectionRect, Portal } from "./utils/selection";

const TOOLBAR_OFFSET_HEIGHT = 40;
const TOOLBAR_OFFSET_WIDTH = 340;
Expand All @@ -29,36 +29,38 @@ export const MenuToolBar: FC<{
}> = props => {
const editor = props.editor;
const keepStatus = useRef(false);
const [top, setTop] = useState(0);
const [left, setLeft] = useState(0);
const [visible, setVisible] = useState(false);
const toolbarRef = useRef<HTMLDivElement>(null);
const [isMouseDown, setIsMouseDown] = useState(false);
const [selectedMarks, setSelectedMarks] = useState<string[]>([]);

const wakeUpToolbar = useMemoFn((wakeUp: boolean) => {
const toolbar = toolbarRef.current;
if (!toolbar) return void 0;
if (ReactEditor.isFocused(editor.raw) && wakeUp) {
setSelectedMarks(
Collection.omit(Object.keys(Editor.marks(editor.raw) || []), NOT_INIT_SELECT)
);
const rect = getSelectionRect();
if (rect) {
toolbar.style.top = `${rect.top + window.pageYOffset - TOOLBAR_OFFSET_HEIGHT - 10}px`;
toolbar.style.left = `${
rect.left + window.pageXOffset - TOOLBAR_OFFSET_WIDTH / 2 + rect.width / 2
}px`;
const t = rect.top + window.scrollY - TOOLBAR_OFFSET_HEIGHT - 10;
const l = rect.left + window.scrollX - TOOLBAR_OFFSET_WIDTH / 2 + rect.width / 2;
setTop(t);
setLeft(l);
}
setVisible(true);
} else {
maskMenuToolBar(toolbar);
setVisible(false);
}
});

useEffect(() => {
const toolbar = toolbarRef.current;
if (!toolbar || props.readonly) return void 0;
if (props.readonly) return void 0;
const mouseUpHandler = () => {
!keepStatus.current && (toolbar.style.display = "");
!keepStatus.current && setIsMouseDown(false);
};
const mouseDownHandler = () => {
!keepStatus.current && (toolbar.style.display = "none");
!keepStatus.current && setIsMouseDown(true);
};
const selectionChangeHandler = () => {
if (keepStatus.current) return void 0;
Expand All @@ -72,7 +74,7 @@ export const MenuToolBar: FC<{
return () => {
document.removeEventListener(EVENT_ENUM.MOUSE_UP, mouseUpHandler);
document.removeEventListener(EVENT_ENUM.MOUSE_DOWN, mouseDownHandler);
document.addEventListener(EVENT_ENUM.SELECTION_CHANGE, selectionChangeHandler);
document.removeEventListener(EVENT_ENUM.SELECTION_CHANGE, selectionChangeHandler);
};
}, [editor, wakeUpToolbar, props.readonly]);

Expand Down Expand Up @@ -115,9 +117,10 @@ export const MenuToolBar: FC<{
[exec, selectedMarks]
);

return props.readonly ? null : (
// 只读状态 / 不可见 / 鼠标按下 时隐藏
return props.readonly || !visible || isMouseDown ? null : (
<Portal>
<div ref={toolbarRef} className="hover-menu-container">
<div ref={toolbarRef} style={{ left, top }} className="hover-menu-container">
{HoverMenu}
</div>
</Portal>
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin/src/float-toolbar/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@
justify-content: center;
}

@keyframes fade-out {
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}

.hover-menu-container {
animation: fade-out 0.3s;
animation: fade-in 0.3s;
background-color: var(--color-bg-2);
border: 1px solid var(--color-border-1);
box-shadow: $box-shadow;
Expand Down
5 changes: 0 additions & 5 deletions packages/plugin/src/float-toolbar/utils/selection.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { Collection } from "doc-editor-utils";
import ReactDOM from "react-dom";

export const maskMenuToolBar = (element: HTMLDivElement) => {
element.style.left = "-1000px";
element.style.top = "-1000px";
};

export const getSelectionRect = () => {
const domSelection = window.getSelection();
if (domSelection && domSelection.rangeCount > 0) {
Expand Down

0 comments on commit a389b50

Please sign in to comment.