From 547dccab644d60bb8db8fe1f179a13fa73f2d55b Mon Sep 17 00:00:00 2001 From: Sandy S Kuo <62935115+kuosandys@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:47:27 +0200 Subject: [PATCH] refactor: use common sortHighlights function --- .../LibraryCards/LibraryHighlightGridCard.tsx | 34 +---------------- .../components/templates/article/Notebook.tsx | 36 +----------------- .../templates/article/NotebookModal.tsx | 7 ---- .../templates/homeFeed/HighlightItem.tsx | 36 +----------------- packages/web/lib/highlights/sortHighlights.ts | 38 +++++++++++++++++++ 5 files changed, 44 insertions(+), 107 deletions(-) create mode 100644 packages/web/lib/highlights/sortHighlights.ts diff --git a/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx b/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx index 4145c7d41..704fa6237 100644 --- a/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx +++ b/packages/web/components/patterns/LibraryCards/LibraryHighlightGridCard.tsx @@ -7,11 +7,11 @@ 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 { getHighlightLocation } from '../../templates/article/NotebookModal' import { Highlight } from '../../../lib/networking/fragments/highlightFragment' import { HighlightView } from '../HighlightView' import { useRouter } from 'next/router' import { showErrorToast } from '../../../lib/toastHelpers' +import { sortHighlights } from '../../../lib/highlights/sortHighlights' export const GridSeparator = styled(Box, { height: '1px', @@ -57,37 +57,7 @@ export function LibraryHighlightGridCard( ) const sortedHighlights = useMemo(() => { - const sorted = (a: number, b: number) => { - if (a < b) { - return -1 - } - if (a > b) { - return 1 - } - return 0 - } - - if (!props.item.highlights) { - return [] - } - - 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) - } - // 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) - }) + return sortHighlights(props.item.highlights ?? []) }, [props.item.highlights]) return ( diff --git a/packages/web/components/templates/article/Notebook.tsx b/packages/web/components/templates/article/Notebook.tsx index a8f6e4504..8ea3cc573 100644 --- a/packages/web/components/templates/article/Notebook.tsx +++ b/packages/web/components/templates/article/Notebook.tsx @@ -4,7 +4,6 @@ import type { Highlight } from '../../../lib/networking/fragments/highlightFragm import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' -import { diff_match_patch } from 'diff-match-patch' import 'react-markdown-editor-lite/lib/index.css' import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' import { v4 as uuidv4 } from 'uuid' @@ -20,6 +19,7 @@ import { ArticleNotes } from '../../patterns/ArticleNotes' import { useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery' import { formattedShortTime } from '../../../lib/dateFormatting' import { isDarkTheme } from '../../../lib/themeUpdater' +import { sortHighlights } from '../../../lib/highlights/sortHighlights' type NotebookContentProps = { viewer: UserBasicData @@ -34,12 +34,6 @@ type NotebookContentProps = { setShowConfirmDeleteNote?: (show: boolean) => void } -export const getHighlightLocation = (patch: string): number | undefined => { - const dmp = new diff_match_patch() - const patches = dmp.patch_fromText(patch) - return patches[0].start1 || undefined -} - type NoteState = { isCreating: boolean note: Highlight | undefined @@ -137,33 +131,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element { }, [props, highlights]) const sortedHighlights = useMemo(() => { - const sorted = (a: number, b: number) => { - if (a < b) { - return -1 - } - if (a > b) { - return 1 - } - return 0 - } - - return (highlights ?? []) - .filter((h) => h.type === 'HIGHLIGHT') - .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) - } - } catch {} - return a.createdAt.localeCompare(b.createdAt) - }) + return sortHighlights(highlights ?? []) }, [highlights]) const handleSaveNoteText = useCallback( diff --git a/packages/web/components/templates/article/NotebookModal.tsx b/packages/web/components/templates/article/NotebookModal.tsx index 4b865af66..6e333287c 100644 --- a/packages/web/components/templates/article/NotebookModal.tsx +++ b/packages/web/components/templates/article/NotebookModal.tsx @@ -12,7 +12,6 @@ import { useCallback, useState } from 'react' import { X } from '@phosphor-icons/react' import { Dropdown, DropdownOption } from '../../elements/DropdownElements' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' -import { diff_match_patch } from 'diff-match-patch' import { MenuTrigger } from '../../elements/MenuTrigger' import { highlightsAsMarkdown } from '../homeFeed/HighlightItem' import 'react-markdown-editor-lite/lib/index.css' @@ -29,12 +28,6 @@ type NotebookModalProps = { onClose: (highlights: Highlight[], deletedHighlights: Highlight[]) => void } -export const getHighlightLocation = (patch: string): number | undefined => { - const dmp = new diff_match_patch() - const patches = dmp.patch_fromText(patch) - return patches[0].start1 || undefined -} - export function NotebookModal(props: NotebookModalProps): JSX.Element { const [showConfirmDeleteNote, setShowConfirmDeleteNote] = useState(false) const [allAnnotations, setAllAnnotations] = useState( diff --git a/packages/web/components/templates/homeFeed/HighlightItem.tsx b/packages/web/components/templates/homeFeed/HighlightItem.tsx index 92343932a..d11d18551 100644 --- a/packages/web/components/templates/homeFeed/HighlightItem.tsx +++ b/packages/web/components/templates/homeFeed/HighlightItem.tsx @@ -11,9 +11,8 @@ import { DropdownSeparator, } from '../../elements/DropdownElements' import { Box, VStack } from '../../elements/LayoutPrimitives' - import { styled, theme } from '../../tokens/stitches.config' -import { getHighlightLocation } from '../article/Notebook' +import { sortHighlights } from '../../../lib/highlights/sortHighlights' type HighlightsMenuProps = { viewer: UserBasicData @@ -133,36 +132,6 @@ export function HighlightsMenu(props: HighlightsMenuProps): JSX.Element { ) } -const sortHighlights = (highlights: Highlight[]) => { - const sorted = (a: number, b: number) => { - if (a < b) { - return -1 - } - if (a > b) { - return 1 - } - return 0 - } - - return (highlights ?? []) - .filter((h) => h.type === 'HIGHLIGHT') - .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) - } - } catch {} - return a.createdAt.localeCompare(b.createdAt) - }) -} - export function highlightAsMarkdown(highlight: Highlight) { let buffer = `> ${highlight.quote}` if (highlight.annotation) { @@ -175,8 +144,7 @@ export function highlightAsMarkdown(highlight: Highlight) { export function highlightsAsMarkdown(highlights: Highlight[]) { const noteMD = highlights.find((h) => h.type == 'NOTE') - const highlightMD = sortHighlights(highlights) - .filter((h) => h.type == 'HIGHLIGHT') + const highlightMD = sortHighlights(highlights ?? []) .map((highlight) => { return highlightAsMarkdown(highlight) }) diff --git a/packages/web/lib/highlights/sortHighlights.ts b/packages/web/lib/highlights/sortHighlights.ts new file mode 100644 index 000000000..3b90c5053 --- /dev/null +++ b/packages/web/lib/highlights/sortHighlights.ts @@ -0,0 +1,38 @@ +import { diff_match_patch } from 'diff-match-patch' +import type { Highlight } from '../networking/fragments/highlightFragment' + +export function sortHighlights(highlights: Highlight[]) { + const sorted = (a: number, b: number) => { + if (a < b) { + return -1 + } + if (a > b) { + return 1 + } + return 0 + } + + const getHighlightLocation = (patch: string): number | undefined => { + const dmp = new diff_match_patch() + const patches = dmp.patch_fromText(patch) + return patches[0].start1 || undefined + } + + return highlights + .filter((h) => h.type === 'HIGHLIGHT') + .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) + } + } catch {} + return a.createdAt.localeCompare(b.createdAt) + }) +}