From d8eda5e42dadef9e8e0c164673dfb3c22ac22a67 Mon Sep 17 00:00:00 2001 From: CatsJuice Date: Fri, 8 Nov 2024 00:48:32 +0000 Subject: [PATCH] refactor(mobile): impl all-docs masonry with css grid, close AF-1598 (#8731) - responsive layout support ![CleanShot 2024-11-07 at 11.51.21.gif](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/LakojjjzZNf6ogjOVwKE/38b3f11f-59a6-42cc-9a41-8b72ce0998ea.gif) --- .../src/mobile/components/doc-card/index.tsx | 27 +++++++++-- .../mobile/components/doc-card/styles.css.tsx | 1 - .../mobile/views/all-docs/doc/masonry.css.ts | 33 ++++---------- .../src/mobile/views/all-docs/doc/masonry.tsx | 45 +++++++++++-------- 4 files changed, 59 insertions(+), 47 deletions(-) diff --git a/packages/frontend/core/src/mobile/components/doc-card/index.tsx b/packages/frontend/core/src/mobile/components/doc-card/index.tsx index dfd0509735978..d3834dd170a47 100644 --- a/packages/frontend/core/src/mobile/components/doc-card/index.tsx +++ b/packages/frontend/core/src/mobile/components/doc-card/index.tsx @@ -10,21 +10,36 @@ import { import type { DocMeta } from '@blocksuite/affine/store'; import { useLiveData, useService, WorkspaceService } from '@toeverything/infra'; import clsx from 'clsx'; -import { forwardRef, type ReactNode } from 'react'; +import { forwardRef, type ReactNode, useMemo } from 'react'; import * as styles from './styles.css'; import { DocCardTags } from './tag'; +const calcRowsById = (id: string) => { + const [MIN, MAX] = [2, 8]; + + const code = id.charCodeAt(0); + return Math.floor((code % (MAX - MIN)) + MIN); +}; + export interface DocCardProps extends Omit { meta: { id: DocMeta['id']; title?: ReactNode; } & { [key: string]: any }; showTags?: boolean; + + /** + * When enabled, preview's height will be calculated based on `meta.id` + */ + autoHeightById?: boolean; } export const DocCard = forwardRef( - function DocCard({ showTags = true, meta, className, ...attrs }, ref) { + function DocCard( + { showTags = true, meta, className, autoHeightById, ...attrs }, + ref + ) { const favAdapter = useService(CompatibleFavoriteItemsAdapter); const workspace = useService(WorkspaceService).workspace; @@ -38,6 +53,12 @@ export const DocCard = forwardRef( [favAdapter, meta.id] ); + const contentStyle = useMemo(() => { + if (!autoHeightById) return { flex: 1 }; + const rows = calcRowsById(meta.id); + return { height: `${rows * 18}px` }; + }, [autoHeightById, meta.id]); + return ( ( } /> -
+
{ + const maxCardWidth = 220; + const windowWidth = window.innerWidth; + const newColumnCount = Math.floor( + (windowWidth - styles.paddingX * 2 - styles.columnGap) / maxCardWidth + ); + return Math.max(newColumnCount, 2); +}; + export const MasonryDocs = ({ items, showTags, @@ -12,25 +21,23 @@ export const MasonryDocs = ({ items: DocMeta[]; showTags?: boolean; }) => { - // card preview is loaded lazily, it's meaningless to calculate height - const stacks = useMemo(() => { - return items.reduce( - (acc, item, i) => { - acc[i % 2].push(item); - return acc; - }, - [[], []] as [DocMeta[], DocMeta[]] - ); - }, [items]); + const [columnCount, setColumnCount] = useState(calcColumnCount); + + const updateColumnCount = useCallback(() => { + setColumnCount(calcColumnCount()); + }, []); + useGlobalEvent('resize', updateColumnCount); return ( -
- {stacks.map((stack, i) => ( -
    - {stack.map(item => ( - - ))} -
+
+ {items.map(item => ( + ))}
);