diff --git a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx index eadc62608..f7965adc2 100644 --- a/packages/web/components/templates/homeFeed/EmptyLibrary.tsx +++ b/packages/web/components/templates/homeFeed/EmptyLibrary.tsx @@ -18,6 +18,7 @@ export function EmptyLibrary(props: EmptyLibraryProps): JSX.Element { color: '$grayTextContrast', textAlign: 'center', paddingTop: '88px', + flex: '1', }} > diff --git a/packages/web/components/templates/homeFeed/HighlightItem.tsx b/packages/web/components/templates/homeFeed/HighlightItem.tsx index 7955f11dd..43fdc60ed 100644 --- a/packages/web/components/templates/homeFeed/HighlightItem.tsx +++ b/packages/web/components/templates/homeFeed/HighlightItem.tsx @@ -21,12 +21,15 @@ import { } from '../../elements/LayoutPrimitives' import { StyledText } from '../../elements/StyledText' import { ConfirmationModal } from '../../patterns/ConfirmationModal' +import { theme } from '../../tokens/stitches.config' import { SetLabelsModal } from '../article/SetLabelsModal' type HighlightItemProps = { highlight: Highlight viewer: UserBasicData | undefined item: LibraryItemNode + + deleteHighlight: (item: LibraryItemNode, highlight: Highlight) => void } const StyledQuote = styled(Blockquote, { @@ -140,10 +143,6 @@ export function HighlightItem(props: HighlightItemProps): JSX.Element { css={{ marginLeft: 'auto', width: '20px', - visibility: hover ? 'unset' : 'hidden', - '@media (hover: none)': { - visibility: 'unset', - }, }} > { - ;(async () => { - const markdown = highlightAsMarkdown(props.highlight) - await navigator.clipboard.writeText(markdown) - showSuccessToast('Highlight copied') - })() - }, [props.highlight]) - return ( - + } > @@ -249,7 +245,7 @@ export function HighlightsMenu(props: HighlightsMenuProps): JSX.Element { /> { - exportHighlight() + props.setShowConfirmDeleteHighlightId(props.highlight.id) }} title="Delete" /> diff --git a/packages/web/components/templates/homeFeed/HighlightsLayout.tsx b/packages/web/components/templates/homeFeed/HighlightsLayout.tsx index 129d0f8f7..425be9134 100644 --- a/packages/web/components/templates/homeFeed/HighlightsLayout.tsx +++ b/packages/web/components/templates/homeFeed/HighlightsLayout.tsx @@ -1,7 +1,11 @@ import { HighlighterCircle } from 'phosphor-react' -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useEffect, useReducer, useState } from 'react' import { Toaster } from 'react-hot-toast' -import { LibraryItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery' +import { Highlight } from '../../../lib/networking/fragments/highlightFragment' +import { + LibraryItem, + LibraryItemNode, +} from '../../../lib/networking/queries/useGetLibraryItemsQuery' import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' import { Dropdown, DropdownOption } from '../../elements/DropdownElements' @@ -14,6 +18,8 @@ import { timeAgo, } from '../../patterns/LibraryCards/LibraryCardStyles' import { LibraryHighlightGridCard } from '../../patterns/LibraryCards/LibraryHighlightGridCard' +import { EmptyHighlights } from './EmptyHighlights' +import { HEADER_HEIGHT, MOBILE_HEADER_HEIGHT } from './HeaderSpacer' import { HighlightItem, highlightsAsMarkdown } from './HighlightItem' type HighlightItemsLayoutProps = { @@ -30,14 +36,74 @@ export function HighlightItemsLayout( undefined ) + const listReducer = ( + state: LibraryItem[], + action: { + type: string + itemId?: string + highlightId?: string + items?: LibraryItem[] + } + ) => { + switch (action.type) { + case 'RESET': + return action.items ?? [] + case 'REMOVE_HIGHLIGHT': + const item = state.find((li) => li.node.id === action.itemId) + if (item && item.node.highlights) { + item.node.highlights = item.node.highlights.filter( + (h) => h.id !== action.highlightId + ) + } + return state.filter( + (item) => item.node.highlights && item.node.highlights.length > 0 + ) + default: + throw new Error() + } + } + + const [items, dispatchList] = useReducer(listReducer, []) + + function handleDelete(item: LibraryItemNode, highlight: Highlight) { + dispatchList({ + type: 'REMOVE_HIGHLIGHT', + itemId: item.id, + highlightId: highlight.id, + }) + } + + useEffect(() => { + dispatchList({ + type: 'RESET', + items: props.items, + }) + }, [props.items]) + useEffect(() => { // Only set the current item on larger screens if (window.innerWidth >= 992 /* lgDown */) { - if (!currentItem && props.items.length > 0) { - setCurrentItem(props.items[0]) + if (!currentItem && items.length > 0) { + setCurrentItem(items[0]) } } - }, [currentItem, setCurrentItem, props.items]) + }, [currentItem, setCurrentItem, items]) + + if (items.length < 1) { + return ( + + + + ) + } return ( <> @@ -45,6 +111,7 @@ export function HighlightItemsLayout( css={{ width: '100%', height: '100%', + position: 'relative', bg: '$thBackground2', }} distribution="start" @@ -63,59 +130,30 @@ export function HighlightItemsLayout( distribution="start" alignment="start" > - - {/* - - */} - - {props.items.map((linkedItem) => ( - { - setCurrentItem(linkedItem) - event.preventDefault() - }} - > - {props.viewer && ( - - )} + {items.length > 0 ? ( + <> + + + + ) : ( + + No highlights found - ))} + )} {currentItem && ( <> @@ -130,7 +168,11 @@ export function HighlightItemsLayout( }, }} > - + )} @@ -139,6 +181,47 @@ export function HighlightItemsLayout( ) } +type LibraryItemsListProps = { + items: LibraryItem[] + viewer: UserBasicData | undefined + + currentItem: LibraryItem | undefined + setCurrentItem: (item: LibraryItem | undefined) => void +} + +function LibraryItemsList(props: LibraryItemsListProps): JSX.Element { + return ( + <> + {props.items.map((linkedItem) => ( + { + props.setCurrentItem(linkedItem) + event.preventDefault() + }} + > + {props.viewer && ( + + )} + + ))} + + ) +} + type HighlightTitleCardProps = { item: LibraryItem viewer: UserBasicData @@ -238,6 +321,8 @@ function HighlightTitleCard(props: HighlightTitleCardProps): JSX.Element { type HighlightListProps = { item: LibraryItem viewer: UserBasicData | undefined + + deleteHighlight: (item: LibraryItemNode, highlight: Highlight) => void } function HighlightList(props: HighlightListProps): JSX.Element { @@ -288,7 +373,7 @@ function HighlightList(props: HighlightListProps): JSX.Element { fontSize: '15px', fontFamily: '$display', width: '100%', - color: '$thTextContrast2', + color: 'thTextContrast2', }} > HIGHLIGHTS @@ -309,6 +394,7 @@ function HighlightList(props: HighlightListProps): JSX.Element { viewer={props.viewer} item={props.item.node} highlight={highlight} + deleteHighlight={props.deleteHighlight} /> ))} diff --git a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx index 5385d4417..c4b0134f6 100644 --- a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx +++ b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx @@ -686,7 +686,7 @@ function HomeFeedGrid(props: HomeFeedContentProps): JSX.Element { setShowFilterMenu={setShowFilterMenu} /> - {props.mode == 'highlights' && ( + {!props.isValidating && props.mode == 'highlights' && (