Skip to content

Commit

Permalink
feat(mobile): use cached random height for all docs masonry
Browse files Browse the repository at this point in the history
  • Loading branch information
CatsJuice committed Nov 7, 2024
1 parent bff5508 commit 9b791b4
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 19 deletions.
17 changes: 15 additions & 2 deletions packages/frontend/core/src/mobile/components/doc-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@ export interface DocCardProps extends Omit<WorkbenchLinkProps, 'to'> {
title?: ReactNode;
} & { [key: string]: any };
showTags?: boolean;

/**
* If provided, content's height will be calculated: `previewRows * line-height`
*/
previewRows?: number;
}

export const DocCard = forwardRef<HTMLAnchorElement, DocCardProps>(
function DocCard({ showTags = true, meta, className, ...attrs }, ref) {
function DocCard(
{ showTags = true, meta, className, previewRows, ...attrs },
ref
) {
const favAdapter = useService(CompatibleFavoriteItemsAdapter);
const workspace = useService(WorkspaceService).workspace;

Expand All @@ -38,6 +46,8 @@ export const DocCard = forwardRef<HTMLAnchorElement, DocCardProps>(
[favAdapter, meta.id]
);

const contentHeight = previewRows ? `${previewRows * 18}px` : 'unset';

return (
<WorkbenchLink
to={`/${meta.id}`}
Expand All @@ -57,7 +67,10 @@ export const DocCard = forwardRef<HTMLAnchorElement, DocCardProps>(
}
/>
</header>
<main className={styles.content}>
<main
className={styles.content}
style={{ height: contentHeight, flex: contentHeight ? 'unset' : 1 }}
>
<PagePreview
docCollection={workspace.docCollection}
pageId={meta.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export const untitled = style({
export const content = style([
footnoteRegular,
{
flex: 1,
overflow: 'hidden',
},
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ export const masonry = style({
columnGap: columnGap,
});
export const masonryItem = style({
display: 'grid',
gridTemplateRows: '1fr auto',
breakInside: 'avoid',
marginBottom: 10,
});
export const space = style({ width: '100%', height: 16 });
48 changes: 35 additions & 13 deletions packages/frontend/core/src/mobile/views/all-docs/doc/masonry.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,63 @@
import { useGlobalEvent } from '@affine/core/mobile/hooks/use-global-events';
import type { DocMeta } from '@blocksuite/affine/store';
import { useCallback, useEffect, useState } from 'react';
import { GlobalCacheService, useService } from '@toeverything/infra';
import { useCallback, useMemo, useState } from 'react';

import { DocCard } from '../../../components';
import * as styles from './masonry.css';

const rows = [3, 4, 5, 6, 7];
const cacheKey = 'masonryPreviewRows';

const calcColumnCount = () => {
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,
}: {
items: DocMeta[];
showTags?: boolean;
}) => {
const [columnCount, setColumnCount] = useState(2);
const globalCache = useService(GlobalCacheService).globalCache;
const [columnCount, setColumnCount] = useState(calcColumnCount());

const updateColumnCount = useCallback(() => {
const maxCardWidth = 220;
const windowWidth = window.innerWidth;
const newColumnCount = Math.floor(
(windowWidth - styles.paddingX * 2 - styles.columnGap) / maxCardWidth
);
setColumnCount(Math.max(newColumnCount, 2));
setColumnCount(calcColumnCount());
}, []);

useGlobalEvent('resize', updateColumnCount);
useEffect(() => {
updateColumnCount();
}, [updateColumnCount]);

// Randomly assign preview rows to each item and cache it
const previewRowsMap = useMemo(() => {
const cache = globalCache.get<Record<string, number>>(cacheKey) || {};
const newCache = items.reduce(
(acc, item) => {
if (cache[item.id]) return acc;
const row = rows[Math.floor(Math.random() * rows.length)];
acc[item.id] = row;
return acc;
},
{ ...cache }
);
globalCache.set(cacheKey, newCache);
return newCache;
}, [globalCache, items]);

return (
<div className={styles.masonry} style={{ columnCount }}>
{items.map(item => (
<DocCard
key={item.id}
className={styles.masonryItem}
previewRows={previewRowsMap[item.id]}
showTags={showTags}
meta={item}
className={styles.masonryItem}
/>
))}
</div>
Expand Down

0 comments on commit 9b791b4

Please sign in to comment.