diff --git a/packages/web/components/patterns/HighlightNotes.tsx b/packages/web/components/patterns/HighlightNotes.tsx index d72ef91b5..e5a78f425 100644 --- a/packages/web/components/patterns/HighlightNotes.tsx +++ b/packages/web/components/patterns/HighlightNotes.tsx @@ -220,6 +220,7 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element { width: '100%', fontSize: '9px', mt: '1px', + bg: 'red', color: '$thTextSubtle', }} alignment="start" @@ -246,6 +247,17 @@ export function MarkdownNote(props: MarkdownNote): JSX.Element { )}`} ) : null} + + Save + ) : ( diff --git a/packages/web/components/patterns/HighlightView.tsx b/packages/web/components/patterns/HighlightView.tsx index 66c2aea11..6fea3acc7 100644 --- a/packages/web/components/patterns/HighlightView.tsx +++ b/packages/web/components/patterns/HighlightView.tsx @@ -28,7 +28,6 @@ const StyledQuote = styled(Blockquote, { export function HighlightView(props: HighlightViewProps): JSX.Element { const [noteMode, setNoteMode] = useState<'preview' | 'edit'>('preview') - const [isEditing, setIsEditing] = useState(false) const lines = useMemo( () => (props.highlight.quote || '').split('\n'), diff --git a/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx b/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx index fb5b4cd1b..8e68081f9 100644 --- a/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx +++ b/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx @@ -1,4 +1,4 @@ -import { Box, VStack, HStack } from '../../elements/LayoutPrimitives' +import { Box, VStack, HStack, SpanBox } from '../../elements/LayoutPrimitives' import { useCallback, useMemo, useState } from 'react' import { CaretDown, CaretUp } from 'phosphor-react' import { MetaStyle, timeAgo, TitleStyle } from './LibraryCardStyles' @@ -7,9 +7,9 @@ import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery import { LibraryItemNode } from '../../../lib/networking/queries/useGetLibraryItemsQuery' import { Button } from '../../elements/Button' import { theme } from '../../tokens/stitches.config' -import { HighlightItem } from '../../templates/homeFeed/HighlightItem' import { getHighlightLocation } from '../../templates/article/NotebookModal' import { Highlight } from '../../../lib/networking/fragments/highlightFragment' +import { HighlightView } from '../HighlightView' export const GridSeparator = styled(Box, { height: '1px', @@ -46,21 +46,23 @@ export function LibraryHighlightGridCard( return [] } - return props.item.highlights.sort((a: Highlight, b: Highlight) => { - if (a.highlightPositionPercent && b.highlightPositionPercent) { - return sorted(a.highlightPositionPercent, b.highlightPositionPercent) - } - // We do this in a try/catch because it might be an invalid diff - // With PDF it will definitely be an invalid diff. - try { - const aPos = getHighlightLocation(a.patch) - const bPos = getHighlightLocation(b.patch) - if (aPos && bPos) { - return sorted(aPos, bPos) + return props.item.highlights + .filter((h) => h.type === 'HIGHLIGHT') + .sort((a: Highlight, b: Highlight) => { + if (a.highlightPositionPercent && b.highlightPositionPercent) { + return sorted(a.highlightPositionPercent, b.highlightPositionPercent) } - } catch {} - return a.createdAt.localeCompare(b.createdAt) - }) + // We do this in a try/catch because it might be an invalid diff + // With PDF it will definitely be an invalid diff. + try { + const aPos = getHighlightLocation(a.patch) + const bPos = getHighlightLocation(b.patch) + if (aPos && bPos) { + return sorted(aPos, bPos) + } + } catch {} + return a.createdAt.localeCompare(b.createdAt) + }) }, [props.item.highlights]) return ( @@ -121,17 +123,20 @@ export function LibraryHighlightGridCard( <> {sortedHighlights.map((highlight) => ( - + <> + { + console.log('updated highlight: ', highlight) + }} + /> + + ))} diff --git a/packages/web/components/templates/article/NotebookModal.tsx b/packages/web/components/templates/article/NotebookModal.tsx index c4d2e4432..6cc35eed1 100644 --- a/packages/web/components/templates/article/NotebookModal.tsx +++ b/packages/web/components/templates/article/NotebookModal.tsx @@ -28,6 +28,7 @@ import { v4 as uuidv4 } from 'uuid' import { nanoid } from 'nanoid' import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' import { HighlightNoteBox } from '../../patterns/HighlightNotes' +import { HighlightViewItem } from './HighlightViewItem' type NotebookModalProps = { pageId: string @@ -77,7 +78,6 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { deleteHighlightId?: string | undefined } ) => { - console.log('annotationsReducer', action.type) switch (action.type) { case 'RESET': { console.log(' -- reseting highlights: ', action.allHighlights) @@ -382,7 +382,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { {sortedHighlights.map((highlight) => ( - void - deleteHighlightAction: () => void - updateHighlight: (highlight: Highlight) => void - - setSetLabelsTarget: (highlight: Highlight) => void - setShowConfirmDeleteHighlightId: (id: string | undefined) => void -} - -function ModalHighlightView(props: ModalHighlightViewProps): JSX.Element { - const [hover, setHover] = useState(false) - - return ( - setHover(true)} - onMouseLeave={() => setHover(false)} - > - - - - - - - - - - ) -} - type TitledSectionProps = { title: string editMode?: boolean diff --git a/packages/web/components/templates/article/PdfArticleContainer.tsx b/packages/web/components/templates/article/PdfArticleContainer.tsx index 6a36b6a4c..93730bc34 100644 --- a/packages/web/components/templates/article/PdfArticleContainer.tsx +++ b/packages/web/components/templates/article/PdfArticleContainer.tsx @@ -496,7 +496,11 @@ export default function PdfArticleContainer( pageId={props.article.id} highlights={highlightsRef.current} onClose={(updatedHighlights, deletedAnnotations) => { - console.log('closed PDF notebook: ') + console.log( + 'closed PDF notebook: ', + updatedHighlights, + deletedAnnotations + ) props.setShowHighlightsModal(false) }} /> diff --git a/packages/web/components/templates/homeFeed/HighlightItem.tsx b/packages/web/components/templates/homeFeed/HighlightItem.tsx index 8809411de..59cd263cf 100644 --- a/packages/web/components/templates/homeFeed/HighlightItem.tsx +++ b/packages/web/components/templates/homeFeed/HighlightItem.tsx @@ -1,196 +1,11 @@ -import { styled } from '@stitches/react' -import { useRouter } from 'next/router' import { DotsThreeVertical } from 'phosphor-react' -import { Fragment, useCallback, useMemo, useState } from 'react' +import { useCallback } from 'react' import { Highlight } from '../../../lib/networking/fragments/highlightFragment' -import { Label } from '../../../lib/networking/fragments/labelFragment' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' -import { setLabelsForHighlight } from '../../../lib/networking/mutations/setLabelsForHighlight' -import { 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' -import { HighlightNoteTextEditArea } from '../../elements/HighlightNoteTextEditArea' -import { LabelChip } from '../../elements/LabelChip' -import { - Blockquote, - Box, - HStack, - SpanBox, - VStack, -} from '../../elements/LayoutPrimitives' -import { StyledText } from '../../elements/StyledText' -import { ConfirmationModal } from '../../patterns/ConfirmationModal' +import { Box } from '../../elements/LayoutPrimitives' + 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, { - margin: '0px', - fontSize: '16px', - fontFamily: '$inter', - fontWeight: '500', - lineHeight: '1.50', - color: '$thHighContrast', - paddingLeft: '15px', - borderLeft: '2px solid $omnivoreCtaYellow', -}) - -export function HighlightItem(props: HighlightItemProps): JSX.Element { - const router = useRouter() - const [hover, setHover] = useState(false) - const [isEditing, setIsEditing] = useState(false) - - const lines = useMemo( - () => (props.highlight.quote || '').split('\n'), - [props.highlight.quote] - ) - - const [showConfirmDeleteHighlightId, setShowConfirmDeleteHighlightId] = - useState(undefined) - const [labelsTarget, setLabelsTarget] = useState( - undefined - ) - const [, updateState] = useState({}) - - return ( - <> - setHover(true)} - onMouseLeave={() => setHover(false)} - > - - { - if (router && props.viewer) { - const dest = `/${props.viewer.profile.username}/${props.item.slug}#${props.highlight.id}` - router.push(dest) - } - event.preventDefault() - }} - > - - {lines.map((line: string, index: number) => ( - - {line} - {index !== lines.length - 1 && ( - <> -
-
- - )} -
- ))} -
-
- - - {props.highlight.labels?.map((label: Label, index: number) => ( - - ))} - - - {!isEditing && ( - setIsEditing(true)} - > - {props.highlight.annotation - ? props.highlight.annotation - : 'Add notes to this highlight...'} - - )} - {isEditing && ( - {}} - /> - )} -
- - - -
- {showConfirmDeleteHighlightId && ( - { - setShowConfirmDeleteHighlightId(undefined) - const result = await deleteHighlightMutation( - showConfirmDeleteHighlightId - ) - if (result) { - showSuccessToast('Highlight deleted') - props.deleteHighlight(props.item, props.highlight) - } else { - showErrorToast('Error deleting highlight') - } - }} - onOpenChange={() => setShowConfirmDeleteHighlightId(undefined)} - /> - )} - {labelsTarget && ( - { - const result = setLabelsForHighlight( - labelsTarget.id, - labels.map((label) => label.id) - ) - return result - }} - /> - )} - - ) -} type HighlightsMenuProps = { highlight: Highlight @@ -201,10 +16,15 @@ type HighlightsMenuProps = { export function HighlightsMenu(props: HighlightsMenuProps): JSX.Element { const copyHighlight = useCallback(() => { - ;(async () => { - await navigator.clipboard.writeText(props.highlight.quote) - showSuccessToast('Highlight copied') - })() + const quote = props.highlight.quote + if (quote) { + ;(async () => { + await navigator.clipboard.writeText(quote) + showSuccessToast('Highlight copied') + })() + } else { + showErrorToast('No highlight text.') + } }, [props.highlight]) return ( diff --git a/packages/web/components/templates/homeFeed/HighlightsLayout.tsx b/packages/web/components/templates/homeFeed/HighlightsLayout.tsx index 27f04fd28..99a9f7ea1 100644 --- a/packages/web/components/templates/homeFeed/HighlightsLayout.tsx +++ b/packages/web/components/templates/homeFeed/HighlightsLayout.tsx @@ -1,5 +1,5 @@ import { HighlighterCircle } from 'phosphor-react' -import { useCallback, useEffect, useReducer, useState } from 'react' +import { useCallback, useEffect, useMemo, useReducer, useState } from 'react' import { Toaster } from 'react-hot-toast' import { Highlight } from '../../../lib/networking/fragments/highlightFragment' import { @@ -13,14 +13,17 @@ import { Dropdown, DropdownOption } from '../../elements/DropdownElements' import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' import { MenuTrigger } from '../../elements/MenuTrigger' import { StyledText } from '../../elements/StyledText' +import { HighlightNoteBox } from '../../patterns/HighlightNotes' +import { HighlightView } from '../../patterns/HighlightView' import { MetaStyle, timeAgo, } from '../../patterns/LibraryCards/LibraryCardStyles' import { LibraryHighlightGridCard } from '../../patterns/LibraryCards/LibraryHighlightGridCard' +import { HighlightViewItem } from '../article/HighlightViewItem' import { EmptyHighlights } from './EmptyHighlights' import { HEADER_HEIGHT, MOBILE_HEADER_HEIGHT } from './HeaderSpacer' -import { HighlightItem, highlightsAsMarkdown } from './HighlightItem' +import { highlightsAsMarkdown } from './HighlightItem' type HighlightItemsLayoutProps = { items: LibraryItem[] @@ -165,7 +168,7 @@ export function HighlightItemsLayout( borderBottom: '1px solid $thBorderColor', }} alignment="center" - distribution="start" + distribution="center" > ( + 'preview' + ) const exportHighlights = useCallback(() => { ;(async () => { if (!props.item.node.highlights) { @@ -378,6 +384,20 @@ function HighlightList(props: HighlightListProps): JSX.Element { })() }, [props.item.node.highlights]) + const note = useMemo(() => { + const note = (props.item.node.highlights ?? []).find( + (h) => h.type === 'NOTE' + ) + console.log('NOTE: ', note) + return note + }, [props.item]) + + const sortedHighlights = useMemo(() => { + return (props.item.node.highlights ?? []).filter( + (h) => h.type === 'HIGHLIGHT' + ) + }, [props.item]) + return ( - HIGHLIGHTS + NOTEBOOK }> - - {(props.item.node.highlights ?? []).map((highlight) => ( - - ))} - - + + + + NOTE + + + { + console.log('saving text', highlight) + }} + /> + + + {sortedHighlights && ( + <> + + + HIGHLIGHTS + + + + {sortedHighlights.map((highlight) => ( + <> + { + console.log('updated highlight: ', highlight) + }} + /> + + + ))} + + + + + )} )