mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-27 02:42:25 +08:00
refactor: refactor lock scroll
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable filename-rules/match */
|
/* eslint-disable filename-rules/match */
|
||||||
import { useEffect, useRef, type UIEvent } from 'react';
|
import { useEffect, useRef, type UIEvent, useState } from 'react';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import {
|
import {
|
||||||
MuiBox as Box,
|
MuiBox as Box,
|
||||||
@@ -37,8 +37,6 @@ export function Page(props: PageProps) {
|
|||||||
const { user } = useUserAndSpaces();
|
const { user } = useUserAndSpaces();
|
||||||
const templatesPortalFlag = useFlag('BooleanTemplatesPortal', false);
|
const templatesPortalFlag = useFlag('BooleanTemplatesPortal', false);
|
||||||
const dailyNotesFlag = useFlag('BooleanDailyNotes', false);
|
const dailyNotesFlag = useFlag('BooleanDailyNotes', false);
|
||||||
const editorRef = useRef<BlockEditor>();
|
|
||||||
const scrollContainerRef = useRef();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!user?.id || !page_id) return;
|
if (!user?.id || !page_id) return;
|
||||||
@@ -61,16 +59,6 @@ export function Page(props: PageProps) {
|
|||||||
updateRecentPages();
|
updateRecentPages();
|
||||||
}, [user, props.workspace, page_id]);
|
}, [user, props.workspace, page_id]);
|
||||||
|
|
||||||
const onScroll = (event: UIEvent) => {
|
|
||||||
editorRef.current.getHooks().onRootNodeScroll(event);
|
|
||||||
editorRef.current.scrollManager.emitScrollEvent(event);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
editorRef.current.scrollManager.scrollContainer =
|
|
||||||
scrollContainerRef.current;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LigoApp>
|
<LigoApp>
|
||||||
<LigoLeftContainer style={{ width: fixedDisplay ? '300px' : 0 }}>
|
<LigoLeftContainer style={{ width: fixedDisplay ? '300px' : 0 }}>
|
||||||
@@ -115,11 +103,46 @@ export function Page(props: PageProps) {
|
|||||||
</WorkspaceSidebarContent>
|
</WorkspaceSidebarContent>
|
||||||
</WorkspaceSidebar>
|
</WorkspaceSidebar>
|
||||||
</LigoLeftContainer>
|
</LigoLeftContainer>
|
||||||
<LigoRightContainer ref={scrollContainerRef} onScroll={onScroll}>
|
<EditorContainer workspace={props.workspace} pageId={page_id} />
|
||||||
{page_id ? (
|
</LigoApp>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EditorContainer = ({
|
||||||
|
pageId,
|
||||||
|
workspace,
|
||||||
|
}: {
|
||||||
|
pageId: string;
|
||||||
|
workspace: string;
|
||||||
|
}) => {
|
||||||
|
const [lockScroll, setLockScroll] = useState(false);
|
||||||
|
const scrollContainerRef = useRef();
|
||||||
|
const editorRef = useRef<BlockEditor>();
|
||||||
|
const onScroll = (event: UIEvent) => {
|
||||||
|
editorRef.current.getHooks().onRootNodeScroll(event);
|
||||||
|
editorRef.current.scrollManager.emitScrollEvent(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
editorRef.current.scrollManager.scrollContainer =
|
||||||
|
scrollContainerRef.current;
|
||||||
|
|
||||||
|
editorRef.current.scrollManager.scrollController = {
|
||||||
|
lockScroll: () => setLockScroll(true),
|
||||||
|
unLockScroll: () => setLockScroll(false),
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledEditorContainer
|
||||||
|
lockScroll={lockScroll}
|
||||||
|
ref={scrollContainerRef}
|
||||||
|
onScroll={onScroll}
|
||||||
|
>
|
||||||
|
{pageId ? (
|
||||||
<AffineEditor
|
<AffineEditor
|
||||||
workspace={props.workspace}
|
workspace={workspace}
|
||||||
rootBlockId={page_id}
|
rootBlockId={pageId}
|
||||||
ref={editorRef}
|
ref={editorRef}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -134,10 +157,19 @@ export function Page(props: PageProps) {
|
|||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</LigoRightContainer>
|
</StyledEditorContainer>
|
||||||
</LigoApp>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const StyledEditorContainer = styled('div')<{ lockScroll: boolean }>(
|
||||||
|
({ lockScroll }) => {
|
||||||
|
return {
|
||||||
|
width: '100%',
|
||||||
|
overflowY: lockScroll ? 'hidden' : 'auto',
|
||||||
|
flex: 'auto',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const LigoApp = styled('div')({
|
const LigoApp = styled('div')({
|
||||||
width: '100vw',
|
width: '100vw',
|
||||||
@@ -147,12 +179,6 @@ const LigoApp = styled('div')({
|
|||||||
margin: '10px 0',
|
margin: '10px 0',
|
||||||
});
|
});
|
||||||
|
|
||||||
const LigoRightContainer = styled('div')({
|
|
||||||
width: '100%',
|
|
||||||
overflowY: 'auto',
|
|
||||||
flex: 'auto',
|
|
||||||
});
|
|
||||||
|
|
||||||
const LigoLeftContainer = styled('div')({
|
const LigoLeftContainer = styled('div')({
|
||||||
flex: '0 0 auto',
|
flex: '0 0 auto',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ html {
|
|||||||
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Tahoma,
|
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Tahoma,
|
||||||
PingFang SC, Microsoft Yahei, Arial, Hiragino Sans GB, sans-serif,
|
PingFang SC, Microsoft Yahei, Arial, Hiragino Sans GB, sans-serif,
|
||||||
Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||||
|
/* prevent page shaking when scroll show or hide*/
|
||||||
|
padding-left: calc(100vw - 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -9,27 +9,9 @@ import { AsyncBlock } from '../block';
|
|||||||
type VerticalTypes = 'up' | 'down' | null;
|
type VerticalTypes = 'up' | 'down' | null;
|
||||||
type HorizontalTypes = 'left' | 'right' | null;
|
type HorizontalTypes = 'left' | 'right' | null;
|
||||||
|
|
||||||
const setStyle = (dom: HTMLElement, style: CSSProperties) => {
|
type ScrollController = {
|
||||||
const styleStr = Object.entries(style).reduce(
|
lockScroll: () => void;
|
||||||
(styleStr, [styleName, styleValue]) => {
|
unLockScroll: () => void;
|
||||||
return `${styleStr} ${styleName}: ${styleValue};`;
|
|
||||||
},
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
dom.setAttribute('style', styleStr);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 这里只获取 style 里设置过的属性
|
|
||||||
// 在恢复 body 后重新设置,不需要获取计算属性
|
|
||||||
const getStyle = (dom: HTMLElement, styleName: any) => {
|
|
||||||
return dom.style[styleName];
|
|
||||||
};
|
|
||||||
const getStyles = (dom: HTMLElement, styleNames: any[]) => {
|
|
||||||
return styleNames.reduce((style, styleName) => {
|
|
||||||
style[styleName] = getStyle(dom, styleName);
|
|
||||||
return style;
|
|
||||||
}, {});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ScrollManager {
|
export class ScrollManager {
|
||||||
@@ -44,12 +26,10 @@ export class ScrollManager {
|
|||||||
private _scrollMoveOffset = 8;
|
private _scrollMoveOffset = 8;
|
||||||
private _autoScrollMoveOffset = 8;
|
private _autoScrollMoveOffset = 8;
|
||||||
private _scrollingEvent = new EventEmitter();
|
private _scrollingEvent = new EventEmitter();
|
||||||
private _isFrozen = false;
|
private _scrollController: ScrollController;
|
||||||
private _scrollContainerStyle: CSSProperties = {};
|
|
||||||
|
|
||||||
constructor(editor: BlockEditor) {
|
constructor(editor: BlockEditor) {
|
||||||
this._editor = editor;
|
this._editor = editor;
|
||||||
|
|
||||||
(window as any).scrollManager = this;
|
(window as any).scrollManager = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +62,14 @@ export class ScrollManager {
|
|||||||
this._scrollContainer = dom;
|
this._scrollContainer = dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get scrollController() {
|
||||||
|
return this._scrollController;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set scrollController(controller: ScrollController) {
|
||||||
|
this._scrollController = controller;
|
||||||
|
}
|
||||||
|
|
||||||
public get verticalScrollTriggerDistance() {
|
public get verticalScrollTriggerDistance() {
|
||||||
return 15;
|
return 15;
|
||||||
}
|
}
|
||||||
@@ -308,46 +296,11 @@ export class ScrollManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public frozen() {
|
public lock() {
|
||||||
if (this._isFrozen) {
|
this._scrollController.lockScroll();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._scrollContainerStyle = getStyles(this._scrollContainer, [
|
public unLock() {
|
||||||
// 'position',
|
this._scrollController.unLockScroll();
|
||||||
// 'top',
|
|
||||||
// 'left',
|
|
||||||
'overflow',
|
|
||||||
'height',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// const [recordScrollLeft, recordScrollTop] = this._scrollRecord;
|
|
||||||
|
|
||||||
setStyle(this._scrollContainer, {
|
|
||||||
// Position style maybe should set in mobile
|
|
||||||
|
|
||||||
// position: 'fixed',
|
|
||||||
// top: `-${recordScrollTop}px`,
|
|
||||||
// left: `-${recordScrollLeft}px`,
|
|
||||||
overflow: 'hidden',
|
|
||||||
height: '100%',
|
|
||||||
});
|
|
||||||
|
|
||||||
this._isFrozen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public thaw() {
|
|
||||||
if (!this._isFrozen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setStyle(this._scrollContainer, this._scrollContainerStyle);
|
|
||||||
|
|
||||||
const [recordScrollLeft, recordScrollTop] = this._scrollRecord;
|
|
||||||
this._scrollContainer.scrollTo(recordScrollLeft, recordScrollTop);
|
|
||||||
|
|
||||||
this._scrollContainerStyle = {};
|
|
||||||
|
|
||||||
this._isFrozen = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user