Skip to content

Commit

Permalink
Lazy loading of collections
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnThomson committed Jan 14, 2022
1 parent 53dddfd commit 50e9ea8
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
7 changes: 4 additions & 3 deletions src/BloomBrowserUI/collectionsTab/BookButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
MenuItemSpec
} from "./BooksOfCollection";

export const bookButtonHeight = 120;

export const BookButton: React.FunctionComponent<{
book: IBookInfo;
collection: ICollection;
Expand Down Expand Up @@ -190,7 +192,6 @@ export const BookButton: React.FunctionComponent<{
props.book.title
);

const buttonHeight = 120;
const renameHeight = 40;
const downSize = 14; // size of down-arrow icon

Expand Down Expand Up @@ -270,7 +271,7 @@ export const BookButton: React.FunctionComponent<{
(teamCollectionStatus?.who ? " checkedOut" : "")
}
css={css`
height: ${buttonHeight}px;
height: ${bookButtonHeight}px;
width: 90px;
border: none;
overflow: hidden;
Expand Down Expand Up @@ -372,7 +373,7 @@ export const BookButton: React.FunctionComponent<{
height: ${renameHeight}px;
margin-left: 1px;
border: 1px solid ${kBloomLightBlue};
top: ${buttonHeight - renameHeight - 6}px;
top: ${bookButtonHeight - renameHeight - 6}px;
padding-top: 4px;
position: absolute;
font-size: 12px;
Expand Down
32 changes: 30 additions & 2 deletions src/BloomBrowserUI/collectionsTab/BooksOfCollection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import { BloomApi } from "../utils/bloomApi";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import NestedMenuItem from "material-ui-nested-menu-item";
import { BookButton } from "./BookButton";
import { BookButton, bookButtonHeight } from "./BookButton";
import { useMonitorBookSelection } from "../app/selectedBook";
import { element } from "prop-types";
import { useL10n } from "../react_components/l10nHooks";
import { useState } from "react";
import { useSubscribeToWebSocketForEvent } from "../utils/WebSocketManager";
import { Divider } from "@material-ui/core";
import { BookSelectionManager, useIsSelected } from "./bookSelectionManager";
import LazyLoad from "react-lazyload";

export interface IBookInfo {
id: string;
Expand All @@ -33,6 +34,11 @@ export const BooksOfCollection: React.FunctionComponent<{
collectionId: string;
isEditableCollection: boolean;
manager: BookSelectionManager;
// If supplied, the collection will be wrapped in a LazyLoad so that most of its rendering
// isn't done until it is visible on screen. This requires that we can identify the containing
// element which actually scrolls the BooksOfCollection into and out of view. This prop is
// required to be a selector which will select that exact element.
lazyContainer?: string;
}> = props => {
if (!props.collectionId) {
window.alert("null collectionId");
Expand Down Expand Up @@ -139,7 +145,13 @@ export const BooksOfCollection: React.FunctionComponent<{
props.collectionId
);

return (
// This is an approximation. 5 buttons per line is about what we get in a default
// layout on a fairly typical screen. We'd get a better approximation if we used
// the width of a button and knew the width of the container. But I think this is good
// enough. Worst case, we expand a bit more than we need.
const collectionHeight = bookButtonHeight * Math.ceil(books.length / 5);

const content = (
<div
key={"BookCollection-" + props.collectionId}
className="bookButtonPane"
Expand Down Expand Up @@ -179,6 +191,22 @@ export const BooksOfCollection: React.FunctionComponent<{
)}
</div>
);
// There's no point in lazily loading an empty list of books. But more importantly, on early renders
// before we actually retrieve the list of books, books is always an empty array. If we render a
// LazyLoad at that point, it will have height zero, and then all of them fit on the page, and the
// LazyLoad code determines that they are all visible and expands all of them, and we don't get any
// laziness at all.
return props.lazyContainer && books.length > 0 ? (
<LazyLoad
height={collectionHeight}
scrollContainer={props.lazyContainer}
resize={true} // expand lazy elements as needed when container resizes
>
{content}
</LazyLoad>
) : (
content
);
};

export interface MenuItemSpec {
Expand Down
10 changes: 10 additions & 0 deletions src/BloomBrowserUI/collectionsTab/CollectionsTabPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ export const CollectionsTabPane: React.FunctionComponent<{}> = () => {
collectionId={c.id}
isEditableCollection={false}
manager={manager}
// We need this selector to identify the element that scrolls the collections...
// the one that actually has overflow=auto. This is an element nested inside the
// SplitPane, and (since the documentation of react-collapse-pane is broken) I can't
// find any way to put an explicit id on that element. Nor is there a different
// class automatically applied to the second one. So all I can see to do is
// to get it by finding an element with these two classes that follows another one
// that has them. This is of course using knowledge of the implementation of SplitPane
// which we have no business using, and may break with the next version of SplitPane.
// But I can't find a better option.
lazyContainer=".Pane.horizontal ~ .Pane.horizontal"
/>
</div>
);
Expand Down

0 comments on commit 50e9ea8

Please sign in to comment.