Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added compact mode #140

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 50 additions & 29 deletions packages/web/src/books/bookList/BookList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
import React, { useCallback, FC, memo } from "react"
import React, { useCallback, FC, memo, ReactNode } from "react"
import { Box, useTheme } from "@mui/material"
import { useWindowSize } from "react-use"
import { BookListGridItem } from "./BookListGridItem"
import { LibrarySorting } from "../../library/states"
import { BookListListItem } from "./BookListListItem"
import { ReactWindowList } from "../../common/lists/ReactWindowList"
import { ListActionViewMode } from "../../common/lists/ListActionsToolbar"
import { BookListCompactItem } from "./BookListCompactItem"
import { useListItemHeight } from "./useListItemHeight"

const ItemListContainer = ({
children,
isLast,
borders = false
}: {
children: ReactNode
isLast: boolean
borders?: boolean
}) => (
<Box
style={{
flex: 1,
alignItems: "center",
display: "flex",
height: "100%"
}}
{...(!isLast &&
borders && {
borderBottom: "1px solid",
borderColor: "grey.200"
})}
>
{children}
</Box>
)

export const BookList: FC<{
viewMode?: ListActionViewMode
Expand Down Expand Up @@ -43,47 +71,40 @@ export const BookList: FC<{
: dynamicNumberOfItems
: 1
const adjustedRatioWhichConsiderBottom = theme.custom.coverAverageRatio - 0.1
const densityMultiplier = density === "dense" ? 0.8 : 1
const listItemMargin =
(windowSize.width > theme.breakpoints.values["sm"] ? 20 : 10) *
densityMultiplier
const itemHeight =
viewMode === "grid"
? undefined
: ((windowSize.width > theme.breakpoints.values["sm"] ? 200 : 150) *
theme.custom.coverAverageRatio +
listItemMargin) *
densityMultiplier
const { itemHeight, itemMargin } = useListItemHeight({
density,
viewMode
})

// const rowBorderColor = theme.palette.grey[100]

const rowRenderer = useCallback(
(item: string, _: number, isLast: boolean) => {
return viewMode === "grid" ? (
<BookListGridItem bookId={item} />
) : (
<Box
{...(!isLast &&
{
// borderBottom: `1px solid ${rowBorderColor}`
})}
style={{
flex: 1,
alignItems: "center",
display: "flex",
height: "100%"
}}
>
) : viewMode === "list" ? (
<ItemListContainer isLast={isLast}>
<BookListListItem
bookId={item}
itemHeight={(itemHeight || 0) - listItemMargin}
itemHeight={(itemHeight || 0) - itemMargin}
onItemClick={onItemClick}
withDrawerActions={withBookActions}
pl={1}
/>
</ItemListContainer>
) : (
<ItemListContainer isLast={isLast} borders>
<BookListCompactItem
bookId={item}
itemHeight={(itemHeight || 0) - itemMargin}
onItemClick={onItemClick}
withDrawerActions={withBookActions}
pl={1}
/>
</Box>
</ItemListContainer>
)
},
[viewMode, itemHeight, listItemMargin, onItemClick, withBookActions]
[viewMode, itemHeight, itemMargin, onItemClick, withBookActions]
)

if (props.static) {
Expand All @@ -104,7 +125,7 @@ export const BookList: FC<{
}

return (
<Box style={style} px={isHorizontal ? 0 : 1} display="flex">
<Box style={style} display="flex">
<ReactWindowList
data={data}
rowRenderer={rowRenderer}
Expand Down
15 changes: 15 additions & 0 deletions packages/web/src/books/bookList/BookListCompactItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ComponentProps, memo } from "react"
import { BookListListItem } from "./BookListListItem"

export const BookListCompactItem = memo(
({ ...rest }: ComponentProps<typeof BookListListItem>) => {
return (
<BookListListItem
withCover={false}
withAuthors={false}
withDownloadIcons
{...rest}
/>
)
}
)
26 changes: 15 additions & 11 deletions packages/web/src/books/bookList/BookListCoverContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { FC, memo } from "react"
import { Box, Chip, useTheme } from "@mui/material"
import { Box, BoxProps, Chip, useTheme } from "@mui/material"
import {
CheckOutlined,
CloudDownloadRounded,
Expand All @@ -18,23 +18,26 @@ import { CoverIconBadge } from "./CoverIconBadge"

type Book = ReturnType<typeof useBook>["data"]

export const BookListCoverContainer: FC<{
bookId: string
className?: string
style?: React.CSSProperties
withReadingProgressStatus?: boolean
withDownloadStatus?: boolean
withBadges: boolean
size?: "small" | "large" | "medium"
}> = memo(
export const BookListCoverContainer: FC<
{
bookId: string
className?: string
style?: React.CSSProperties
withReadingProgressStatus?: boolean
withDownloadStatus?: boolean
withBadges: boolean
size?: "small" | "large" | "medium"
} & BoxProps
> = memo(
({
bookId,
className,
style,
withDownloadStatus = true,
withReadingProgressStatus = true,
withBadges,
size = "small"
size = "small",
...rest
}) => {
const { data: item } = useBook({ id: bookId })
const bookDownloadState = useBookDownloadState(bookId)
Expand All @@ -45,6 +48,7 @@ export const BookListCoverContainer: FC<{
<Box
style={{ ...classes.coverContainer, ...style }}
className={className}
{...rest}
>
{item && <Cover bookId={item?._id} />}
{bookDownloadState?.downloadState !== DownloadState.Downloaded && (
Expand Down
81 changes: 56 additions & 25 deletions packages/web/src/books/bookList/BookListListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Box, Chip, Stack, Typography, useTheme } from "@mui/material"
import { Box, BoxProps, Chip, Stack, Typography, useTheme } from "@mui/material"
import { FC, memo } from "react"
import { useDefaultItemClickHandler } from "./helpers"
import { useBook, useIsBookProtected } from "../states"
import { ReadingStateState } from "@oboku/shared"
import {
CloudDoneRounded,
CloudDownloadRounded,
DoneRounded,
DownloadDoneRounded,
DownloadingRounded,
ErrorRounded,
LoopRounded,
MenuBookRounded,
Expand All @@ -16,21 +20,31 @@ import { bookActionDrawerSignal } from "../drawer/BookActionsDrawer"
import { useCSS } from "../../common/utils"
import { BookListCoverContainer } from "./BookListCoverContainer"
import { getMetadataFromBook } from "../getMetadataFromBook"
import { useBookDownloadState } from "../../download/states"

export const BookListListItem: FC<{
bookId: string
onItemClick?: (id: string) => void
isSelected?: (id: string) => boolean
size?: "small" | "large"
itemHeight?: number
withDrawerActions?: boolean
}> = memo(
export const BookListListItem: FC<
{
bookId: string
onItemClick?: (id: string) => void
isSelected?: (id: string) => boolean
size?: "small" | "large"
itemHeight?: number
withDrawerActions?: boolean
withCover?: boolean
withAuthors?: boolean
withDownloadIcons?: boolean
} & BoxProps
> = memo(
({
bookId,
onItemClick,
size = "large",
itemHeight,
withDrawerActions = true
withDrawerActions = true,
withCover = true,
withAuthors = true,
withDownloadIcons = false,
...rest
}) => {
const { data: book } = useBook({
id: bookId
Expand All @@ -40,6 +54,7 @@ export const BookListListItem: FC<{
const computedHeight = itemHeight || (size === "small" ? 50 : 100)
const coverWidth = computedHeight * theme.custom.coverAverageRatio
const classes = useStyles({ coverWidth })
const bookDownloadState = useBookDownloadState(bookId)
const { data: isBookProtected = true } = useIsBookProtected(book)

const metadata = getMetadataFromBook(book)
Expand All @@ -57,20 +72,23 @@ export const BookListListItem: FC<{
cursor: "pointer",
flexGrow: 1
}}
{...rest}
>
<BookListCoverContainer
bookId={bookId}
style={classes.coverContainer}
withBadges={false}
withReadingProgressStatus={false}
/>
{withCover && (
<BookListCoverContainer
bookId={bookId}
style={classes.coverContainer}
withBadges={false}
withReadingProgressStatus={false}
mr={1}
/>
)}
<div
style={{
display: "flex",
flex: 1,
minHeight: 0,
flexDirection: "column",
marginLeft: theme.spacing(1),
overflow: "hidden"
}}
>
Expand All @@ -84,9 +102,11 @@ export const BookListListItem: FC<{
>
{metadata?.title || "Unknown"}
</Typography>
<Typography noWrap color="textSecondary" variant="body2">
{(metadata?.authors ?? [])[0] || "Unknown"}
</Typography>
{withAuthors && (
<Typography noWrap color="textSecondary" variant="body2">
{(metadata?.authors ?? [])[0] || "Unknown"}
</Typography>
)}
<Box
style={{
display: "flex",
Expand All @@ -96,17 +116,28 @@ export const BookListListItem: FC<{
}}
>
<Box display="flex" flexDirection="row" gap={1}>
{isBookProtected && <NoEncryptionRounded />}
{book?.isNotInterested && <ThumbDownOutlined />}
{withDownloadIcons && (
<>
{bookDownloadState?.isDownloading ? (
<DownloadingRounded color="action" />
) : bookDownloadState?.isDownloaded ? (
<CloudDoneRounded color="action" />
) : (
<CloudDownloadRounded color="action" />
)}
</>
)}
{isBookProtected && <NoEncryptionRounded color="action" />}
{book?.isNotInterested && <ThumbDownOutlined color="action" />}
{book?.readingStateCurrentState ===
ReadingStateState.Finished && (
<div style={{ display: "flex", flexDirection: "row" }}>
<DoneRounded style={{}} />
<DoneRounded style={{}} color="action" />
</div>
)}
{book?.readingStateCurrentState === ReadingStateState.Reading && (
<div style={{ display: "flex", flexDirection: "row" }}>
<MenuBookRounded />
<MenuBookRounded color="action" />
<Typography
style={{
marginLeft: theme.spacing(0.5)
Expand Down Expand Up @@ -165,7 +196,7 @@ export const BookListListItem: FC<{
{withDrawerActions && (
<Stack
justifyContent="center"
width={[30, 50]}
width={[40, 50]}
flexDirection="row"
style={{
alignItems: "center",
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/books/bookList/BookListWithControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ export const BookListWithControls: FC<
}}
>
<ListActionsToolbar
viewMode={viewMode}
viewMode={viewMode ?? "grid"}
onViewModeChange={onViewModeChange}
sorting={sorting}
sorting={sorting ?? "alpha"}
onSortingChange={onSortingChange}
/>
<div
Expand Down
Loading