chore: improves scrolling performance and loading component for dark theme (#8795)

What's Changed

* improve scrolling performance
* loading component for dark theme
This commit is contained in:
fundon
2024-11-13 02:25:03 +00:00
parent 17c247af53
commit b5fa8472d9
5 changed files with 71 additions and 123 deletions

View File

@@ -15,13 +15,18 @@ import {
type PDFVirtuosoContext, type PDFVirtuosoContext,
type PDFVirtuosoProps, type PDFVirtuosoProps,
Scroller, Scroller,
ScrollSeekPlaceholder,
} from '@affine/core/modules/pdf/views'; } from '@affine/core/modules/pdf/views';
import type { AttachmentBlockModel } from '@blocksuite/affine/blocks'; import type { AttachmentBlockModel } from '@blocksuite/affine/blocks';
import { CollapseIcon, ExpandIcon } from '@blocksuite/icons/rc'; import { CollapseIcon, ExpandIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useService } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso'; import {
type ScrollSeekConfiguration,
Virtuoso,
type VirtuosoHandle,
} from 'react-virtuoso';
import * as styles from './styles.css'; import * as styles from './styles.css';
import { calculatePageNum } from './utils'; import { calculatePageNum } from './utils';
@@ -112,6 +117,13 @@ const PDFViewerInner = ({ pdf, state }: PDFViewerInnerProps) => {
}; };
}, [state, viewportInfo, onPageSelect]); }, [state, viewportInfo, onPageSelect]);
const scrollSeekConfig = useMemo<ScrollSeekConfiguration>(() => {
return {
enter: velocity => Math.abs(velocity) > 1024,
exit: velocity => Math.abs(velocity) < 10,
};
}, []);
useEffect(() => { useEffect(() => {
const viewer = viewerRef.current; const viewer = viewerRef.current;
if (!viewer) return; if (!viewer) return;
@@ -142,12 +154,14 @@ const PDFViewerInner = ({ pdf, state }: PDFViewerInnerProps) => {
Scroller, Scroller,
Header: ListPadding, Header: ListPadding,
Footer: ListPadding, Footer: ListPadding,
ScrollSeekPlaceholder,
}} }}
context={{ context={{
width: state.meta.width, width: state.meta.width,
height: state.meta.height, height: state.meta.height,
pageClassName: styles.pdfPage, pageClassName: styles.pdfPage,
}} }}
scrollSeekConfiguration={scrollSeekConfig}
/> />
<div className={clsx(['thumbnails', styles.pdfThumbnails])}> <div className={clsx(['thumbnails', styles.pdfThumbnails])}>
<div className={clsx([styles.pdfThumbnailsList, { collapsed }])}> <div className={clsx([styles.pdfThumbnailsList, { collapsed }])}>
@@ -159,9 +173,11 @@ const PDFViewerInner = ({ pdf, state }: PDFViewerInnerProps) => {
itemContent={pageContent} itemContent={pageContent}
components={{ components={{
Item, Item,
Scroller,
List: ListWithSmallGap, List: ListWithSmallGap,
Scroller,
ScrollSeekPlaceholder,
}} }}
scrollSeekConfiguration={scrollSeekConfig}
style={thumbnailsConfig.style} style={thumbnailsConfig.style}
context={thumbnailsConfig.context} context={thumbnailsConfig.context}
/> />

View File

@@ -84,7 +84,7 @@ export const viewer = style({
display: 'flex', display: 'flex',
flex: 1, flex: 1,
overflow: 'hidden', overflow: 'hidden',
resize: 'both', resize: 'none',
selectors: { selectors: {
'&:before': { '&:before': {
position: 'absolute', position: 'absolute',

View File

@@ -1,7 +1,7 @@
import { Scrollable } from '@affine/component'; import { Scrollable } from '@affine/component';
import clsx from 'clsx'; import clsx from 'clsx';
import { type CSSProperties, forwardRef, memo } from 'react'; import { type CSSProperties, forwardRef, memo } from 'react';
import type { VirtuosoProps } from 'react-virtuoso'; import type { ScrollSeekPlaceholderProps, VirtuosoProps } from 'react-virtuoso';
import * as styles from './styles.css'; import * as styles from './styles.css';
@@ -27,6 +27,26 @@ export const Scroller = forwardRef<HTMLDivElement, PDFVirtuosoProps>(
Scroller.displayName = 'pdf-virtuoso-scroller'; Scroller.displayName = 'pdf-virtuoso-scroller';
export const ScrollSeekPlaceholder = forwardRef<
HTMLDivElement,
ScrollSeekPlaceholderProps & {
context?: PDFVirtuosoContext;
}
>(({ context }, ref) => {
const className = context?.pageClassName;
const width = context?.width ?? 537;
const height = context?.height ?? 759;
const style = { width, aspectRatio: `${width} / ${height}` };
return (
<div className={className} style={style} ref={ref}>
<LoadingSvg />
</div>
);
});
ScrollSeekPlaceholder.displayName = 'pdf-virtuoso-scroll-seek-placeholder';
export const List = forwardRef<HTMLDivElement, PDFVirtuosoProps>( export const List = forwardRef<HTMLDivElement, PDFVirtuosoProps>(
({ context: _, className, ...props }, ref) => { ({ context: _, className, ...props }, ref) => {
return ( return (
@@ -63,13 +83,8 @@ export const ListPadding = () => (
<div style={{ width: '100%', height: '20px' }} /> <div style={{ width: '100%', height: '20px' }} />
); );
export const LoadingSvg = memo(function LoadingSvg({ export const LoadingSvg = memo(
style, ({ className, style }: { className?: string; style?: CSSProperties }) => {
className,
}: {
style?: CSSProperties;
className?: string;
}) {
return ( return (
<svg <svg
className={clsx([styles.pdfLoading, className])} className={clsx([styles.pdfLoading, className])}
@@ -77,109 +92,24 @@ export const LoadingSvg = memo(function LoadingSvg({
width="16" width="16"
height="24" height="24"
viewBox="0 0 537 759" viewBox="0 0 537 759"
fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
fillOpacity="0.07"
> >
<rect width="537" height="759" fill="white" /> <rect x="32" y="82" width="361" height="30" rx="4" />
<rect <rect x="32" y="142" width="444" height="30" rx="4" />
x="32" <rect x="32" y="202" width="387" height="30" rx="4" />
y="82" <rect x="32" y="262" width="461" height="30" rx="4" />
width="361" <rect x="32" y="322" width="282" height="30" rx="4" />
height="30" <rect x="32" y="382" width="361" height="30" rx="4" />
rx="4" <rect x="32" y="442" width="444" height="30" rx="4" />
fill="black" <rect x="32" y="502" width="240" height="30" rx="4" />
fillOpacity="0.07" <rect x="32" y="562" width="201" height="30" rx="4" />
/> <rect x="32" y="622" width="224" height="30" rx="4" />
<rect <rect x="314" y="502" width="191" height="166" rx="4" />
x="32"
y="142"
width="444"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="202"
width="387"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="262"
width="461"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="322"
width="282"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="382"
width="361"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="442"
width="444"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="502"
width="240"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="562"
width="201"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="32"
y="622"
width="224"
height="30"
rx="4"
fill="black"
fillOpacity="0.07"
/>
<rect
x="314"
y="502"
width="191"
height="166"
rx="4"
fill="black"
fillOpacity="0.07"
/>
</svg> </svg>
); );
}); }
);
LoadingSvg.displayName = 'pdf-loading';

View File

@@ -7,5 +7,6 @@ export {
type PDFVirtuosoContext, type PDFVirtuosoContext,
type PDFVirtuosoProps, type PDFVirtuosoProps,
Scroller, Scroller,
ScrollSeekPlaceholder,
} from './components'; } from './components';
export { PDFPageRenderer } from './page-renderer'; export { PDFPageRenderer } from './page-renderer';

View File

@@ -58,6 +58,7 @@ export const pdfPageCanvas = style({
export const pdfLoading = style({ export const pdfLoading = style({
display: 'flex', display: 'flex',
alignSelf: 'center', alignSelf: 'center',
margin: 'auto',
width: '100%', width: '100%',
height: '100%', height: '100%',
maxWidth: '537px', maxWidth: '537px',