diff --git a/packages/web/components/nav-containers/HighlightsContainer.tsx b/packages/web/components/nav-containers/HighlightsContainer.tsx index 5a74fe514..84792e30e 100644 --- a/packages/web/components/nav-containers/HighlightsContainer.tsx +++ b/packages/web/components/nav-containers/HighlightsContainer.tsx @@ -31,6 +31,7 @@ import { highlightColor } from '../../lib/themeUpdater' import { HighlightViewNote } from '../patterns/HighlightNotes' import { theme } from '../tokens/stitches.config' +import { useDeleteHighlight } from '../../lib/networking/highlights/useItemHighlights' const PAGE_SIZE = 10 @@ -131,8 +132,10 @@ function HighlightCard(props: HighlightCardProps): JSX.Element { const [isOpen, setIsOpen] = useState(false) const [showConfirmDeleteHighlightId, setShowConfirmDeleteHighlightId] = useState(undefined) - const [labelsTarget, setLabelsTarget] = - useState(undefined) + const [labelsTarget, setLabelsTarget] = useState( + undefined + ) + const deleteHighlight = useDeleteHighlight() const viewInReader = useCallback( (highlightId: string) => { @@ -283,24 +286,22 @@ function HighlightCard(props: HighlightCardProps): JSX.Element { message={'Are you sure you want to delete this highlight?'} onAccept={() => { ;(async () => { - const highlightId = showConfirmDeleteHighlightId - const success = await deleteHighlightMutation( - props.highlight.libraryItem?.id || '', - showConfirmDeleteHighlightId - ) - props.mutate() - if (success) { - showSuccessToast('Highlight deleted.', { - position: 'bottom-right', - }) - const event = new CustomEvent('deleteHighlightbyId', { - detail: highlightId, - }) - document.dispatchEvent(event) - } else { - showErrorToast('Error deleting highlight', { - position: 'bottom-right', + if (props.highlight.libraryItem) { + const success = await deleteHighlight.mutateAsync({ + itemId: props.highlight.libraryItem?.id, + slug: props.highlight.libraryItem?.slug, + highlightId: showConfirmDeleteHighlightId, }) + + if (success) { + showSuccessToast('Highlight deleted.', { + position: 'bottom-right', + }) + } else { + showErrorToast('Error deleting highlight', { + position: 'bottom-right', + }) + } } })() setShowConfirmDeleteHighlightId(undefined) diff --git a/packages/web/components/nav-containers/HomeContainer.tsx b/packages/web/components/nav-containers/HomeContainer.tsx index 230a0e043..0b31504ab 100644 --- a/packages/web/components/nav-containers/HomeContainer.tsx +++ b/packages/web/components/nav-containers/HomeContainer.tsx @@ -950,12 +950,12 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { useLibraryItemActions() const doArchiveItem = useCallback( - async (libraryItemId: string) => { + async (libraryItemId: string, slug: string) => { dispatch({ type: 'REMOVE_ITEM', payload: libraryItemId, }) - if (!(await archiveItem(libraryItemId))) { + if (!(await archiveItem(libraryItemId, slug))) { // dispatch({ // type: 'REPLACE_ITEM', // itemId: libraryItemId, @@ -966,7 +966,7 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { ) const doDeleteItem = useCallback( - async (libraryItemId: string) => { + async (libraryItemId: string, slug: string) => { dispatch({ type: 'REMOVE_ITEM', payload: libraryItemId, @@ -977,7 +977,7 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { // : libraryItemId, // }) } - if (!(await deleteItem(libraryItemId, undo))) { + if (!(await deleteItem(libraryItemId, slug, undo))) { // dispatch({ // type: 'REPLACE_ITEM', // payload: libraryItemId, @@ -988,12 +988,12 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { ) const doMoveItem = useCallback( - async (libraryItemId: string) => { + async (libraryItemId: string, slug: string) => { dispatch({ type: 'REMOVE_ITEM', payload: libraryItemId, }) - if (!(await moveItem(libraryItemId))) { + if (!(await moveItem(libraryItemId, slug))) { // dispatch({ // type: 'REPLACE_ITEM', // payload: libraryItemId, @@ -1043,13 +1043,13 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { ;(event.target as HTMLElement).click() break case 'e': - doArchiveItem(props.homeItem.id) + doArchiveItem(props.homeItem.id, props.homeItem.slug) break case '#': - doDeleteItem(props.homeItem.id) + doDeleteItem(props.homeItem.id, props.homeItem.slug) break case 'm': - doMoveItem(props.homeItem.id) + doMoveItem(props.homeItem.id, props.homeItem.slug) break case 'o': window.open(props.homeItem.url, '_blank') @@ -1097,8 +1097,7 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { onClick={async (event) => { event.preventDefault() event.stopPropagation() - - await doMoveItem(props.homeItem.id) + await doMoveItem(props.homeItem.id, props.homeItem.slug) }} > @@ -1111,8 +1110,7 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { onClick={async (event) => { event.preventDefault() event.stopPropagation() - - await doArchiveItem(props.homeItem.id) + await doArchiveItem(props.homeItem.id, props.homeItem.slug) }} > @@ -1125,8 +1123,7 @@ const TopPicksItemView = (props: HomeItemViewProps): JSX.Element => { onClick={async (event) => { event.preventDefault() event.stopPropagation() - - await doDeleteItem(props.homeItem.id) + await doDeleteItem(props.homeItem.id, props.homeItem.slug) }} > diff --git a/packages/web/components/patterns/CardMenu.tsx b/packages/web/components/patterns/CardMenu.tsx index 73446847f..859332b5a 100644 --- a/packages/web/components/patterns/CardMenu.tsx +++ b/packages/web/components/patterns/CardMenu.tsx @@ -69,9 +69,13 @@ export function CardMenu(props: CardMenuProps): JSX.Element { { await updateItemReadStatus.mutateAsync({ - id: props.item.id, - readingProgressPercent: 100, - force: true, + itemId: props.item.id, + slug: props.item.slug, + input: { + id: props.item.id, + readingProgressPercent: 100, + force: true, + }, }) }} title="Mark read" @@ -80,9 +84,13 @@ export function CardMenu(props: CardMenuProps): JSX.Element { { await updateItemReadStatus.mutateAsync({ - id: props.item.id, - readingProgressPercent: 0, - force: true, + itemId: props.item.id, + slug: props.item.slug, + input: { + id: props.item.id, + readingProgressPercent: 0, + force: true, + }, }) }} title="Mark unread" diff --git a/packages/web/components/patterns/LibraryCards/LibraryHoverActions.tsx b/packages/web/components/patterns/LibraryCards/LibraryHoverActions.tsx index 08ff50770..09249a7df 100644 --- a/packages/web/components/patterns/LibraryCards/LibraryHoverActions.tsx +++ b/packages/web/components/patterns/LibraryCards/LibraryHoverActions.tsx @@ -107,8 +107,12 @@ export const LibraryHoverActions = (props: LibraryHoverActionsProps) => { style="hoverActionIcon" onClick={async (event) => { await archiveItem.mutateAsync({ - linkId: props.item.id, - archived: props.item.state !== State.ARCHIVED, + itemId: props.item.id, + slug: props.item.slug, + input: { + linkId: props.item.id, + archived: props.item.state !== State.ARCHIVED, + }, }) event.preventDefault() event.stopPropagation() @@ -132,9 +136,14 @@ export const LibraryHoverActions = (props: LibraryHoverActionsProps) => { style="hoverActionIcon" onClick={async (event) => { if (props.item.state == State.DELETED) { - await restoreItem.mutateAsync(props.item.id) - } else { - await deleteItem.mutateAsync(props.item.id) + await restoreItem.mutateAsync({ + itemId: props.item.id, + slug: props.item.slug, + }) + await deleteItem.mutateAsync({ + itemId: props.item.id, + slug: props.item.slug, + }) } event.preventDefault() event.stopPropagation() diff --git a/packages/web/components/templates/article/ArticleContainer.tsx b/packages/web/components/templates/article/ArticleContainer.tsx index 15ab8bdf6..83269f1ac 100644 --- a/packages/web/components/templates/article/ArticleContainer.tsx +++ b/packages/web/components/templates/article/ArticleContainer.tsx @@ -523,9 +523,6 @@ export function ArticleContainer(props: ArticleContainerProps): JSX.Element { item={props.article} scrollToHighlight={highlightHref} highlights={props.article.highlights} - articleTitle={title} - articleAuthor={props.article.author ?? ''} - articleId={props.article.id} isAppleAppEmbed={props.isAppleAppEmbed} highlightBarDisabled={props.highlightBarDisabled} showHighlightsModal={props.showHighlightsModal} diff --git a/packages/web/components/templates/article/EpubContainer.tsx b/packages/web/components/templates/article/EpubContainer.tsx index 8990bf558..a6312b3e5 100644 --- a/packages/web/components/templates/article/EpubContainer.tsx +++ b/packages/web/components/templates/article/EpubContainer.tsx @@ -11,9 +11,6 @@ import { import PSPDFKit from 'pspdfkit' import { Instance, HighlightAnnotation, List, Annotation, Rect } from 'pspdfkit' import type { Highlight } from '../../../lib/networking/fragments/highlightFragment' -import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' -import { mergeHighlightMutation } from '../../../lib/networking/mutations/mergeHighlightMutation' import { useCanShareNative } from '../../../lib/hooks/useCanShareNative' import { pspdfKitKey } from '../../../lib/appConfig' import { NotebookModal } from './NotebookModal' @@ -310,56 +307,6 @@ export default function EpubContainer(props: EpubContainerProps): JSX.Element { {/* EPUB CONTAINER
*/} - {noteTarget && ( - { - const savedHighlight = highlightsRef.current.find( - (other: Highlight) => { - return other.id == highlight.id - } - ) - - if (savedHighlight) { - savedHighlight.annotation = highlight.annotation - } - }} - onOpenChange={() => { - setNoteTarget(undefined) - }} - /> - )} - {props.showHighlightsModal && ( - { - console.log( - 'closed PDF notebook: ', - updatedHighlights, - deletedAnnotations - ) - deletedAnnotations.forEach((highlight) => { - const event = new CustomEvent('deleteHighlightbyId', { - detail: highlight.id, - }) - document.dispatchEvent(event) - }) - props.setShowHighlightsModal(false) - }} - viewHighlightInReader={(highlightId) => { - const event = new CustomEvent('scrollToHighlightId', { - detail: highlightId, - }) - document.dispatchEvent(event) - props.setShowHighlightsModal(false) - }} - /> - )} ) } diff --git a/packages/web/components/templates/article/HighlightNoteModal.tsx b/packages/web/components/templates/article/HighlightNoteModal.tsx index 42b416e04..35caf4d65 100644 --- a/packages/web/components/templates/article/HighlightNoteModal.tsx +++ b/packages/web/components/templates/article/HighlightNoteModal.tsx @@ -13,10 +13,9 @@ import { showErrorToast } from '../../../lib/toastHelpers' import { useUpdateHighlight } from '../../../lib/networking/highlights/useItemHighlights' type HighlightNoteModalProps = { - author: string - title: string highlight?: Highlight libraryItemId: string + libraryItemSlug: string onUpdate: (updatedHighlight: Highlight) => void onOpenChange: (open: boolean) => void createHighlightForNote?: (note?: string) => Promise @@ -43,6 +42,7 @@ export function HighlightNoteModal( try { const result = await updateHighlight.mutateAsync({ itemId: props.libraryItemId, + slug: props.libraryItemSlug, input: { libraryItemId: props.libraryItemId, highlightId: props.highlight?.id, diff --git a/packages/web/components/templates/article/HighlightsLayer.tsx b/packages/web/components/templates/article/HighlightsLayer.tsx index a6023a67d..3232accd0 100644 --- a/packages/web/components/templates/article/HighlightsLayer.tsx +++ b/packages/web/components/templates/article/HighlightsLayer.tsx @@ -39,9 +39,6 @@ type HighlightsLayerProps = { item: ReadableItem highlights: Highlight[] - articleId: string - articleTitle: string - articleAuthor: string isAppleAppEmbed: boolean highlightBarDisabled: boolean showHighlightsModal: boolean @@ -105,7 +102,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { const result = await createHighlight( { selection: selection, - articleId: props.articleId, + articleId: props.item.id, existingHighlights: highlights, color: options?.color, highlightStartEndOffsets: highlightLocations, @@ -141,7 +138,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { [ highlightLocations, highlights, - props.articleId, + props.item.id, props.articleMutations, setSelectionData, ] @@ -189,7 +186,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { const didDeleteHighlight = await props.articleMutations.deleteHighlightMutation( - props.articleId, + props.item.id, highlightId ) @@ -226,7 +223,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { updateHighlightsCallback(highlight) ;(async () => { const update = await props.articleMutations.updateHighlightMutation({ - libraryItemId: props.articleId, + libraryItemId: props.item.id, highlightId: highlight.id, color: color, }) @@ -718,7 +715,7 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { const annotation = event.annotation ?? '' const result = await props.articleMutations.updateHighlightMutation({ - libraryItemId: props.articleId, + libraryItemId: props.item.id, highlightId: focusedHighlight.id, annotation: event.annotation ?? '', }) @@ -800,9 +797,8 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element { {highlightModalAction?.highlightModalAction == 'addComment' && ( setHighlightModalAction({ highlightModalAction: 'none' }) diff --git a/packages/web/components/templates/article/Notebook.tsx b/packages/web/components/templates/article/Notebook.tsx index bc02e9bbd..d70f9ed46 100644 --- a/packages/web/components/templates/article/Notebook.tsx +++ b/packages/web/components/templates/article/Notebook.tsx @@ -5,10 +5,8 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' import 'react-markdown-editor-lite/lib/index.css' -import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' import { v4 as uuidv4 } from 'uuid' import { nanoid } from 'nanoid' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' import { HighlightViewItem } from './HighlightViewItem' import { ConfirmationModal } from '../../patterns/ConfirmationModal' import { TrashIcon } from '../../elements/icons/TrashIcon' @@ -20,6 +18,11 @@ import { formattedShortTime } from '../../../lib/dateFormatting' import { isDarkTheme } from '../../../lib/themeUpdater' import { sortHighlights } from '../../../lib/highlights/sortHighlights' import { useGetLibraryItemContent } from '../../../lib/networking/library_items/useLibraryItems' +import { + useCreateHighlight, + useDeleteHighlight, + useUpdateHighlight, +} from '../../../lib/networking/highlights/useItemHighlights' type NotebookContentProps = { viewer: UserBasicData @@ -42,6 +45,9 @@ type NoteState = { export function NotebookContent(props: NotebookContentProps): JSX.Element { const isDark = isDarkTheme() + const createHighlight = useCreateHighlight() + const deleteHighlight = useDeleteHighlight() + const updateHighlight = useUpdateHighlight() const { data: article } = useGetLibraryItemContent( props.viewer.profile.username as string, @@ -87,12 +93,16 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element { noteState.current.createStarted = new Date() ;(async () => { try { - const success = await createHighlightMutation({ - id: newNoteId, - shortId: nanoid(8), - type: 'NOTE', - articleId: props.item.id, - annotation: text, + const success = await createHighlight.mutateAsync({ + itemId: props.item.id, + slug: props.item.slug, + input: { + id: newNoteId, + shortId: nanoid(8), + type: 'NOTE', + articleId: props.item.id, + annotation: text, + }, }) if (success) { noteState.current.note = success @@ -164,7 +174,11 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element { highlights ?.filter((h) => h.type === 'NOTE') .forEach(async (h) => { - const result = await deleteHighlightMutation(props.item.id, h.id) + const result = await deleteHighlight.mutateAsync({ + itemId: props.item.id, + slug: props.item.slug, + highlightId: h.id, + }) if (!result) { showErrorToast('Error deleting note') } @@ -284,10 +298,11 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element { onAccept={() => { ;(async () => { const highlightId = showConfirmDeleteHighlightId - const success = await deleteHighlightMutation( - props.item.id, - showConfirmDeleteHighlightId - ) + const success = await deleteHighlight.mutateAsync({ + itemId: props.item.id, + slug: props.item.slug, + highlightId: showConfirmDeleteHighlightId, + }) if (success) { showSuccessToast('Highlight deleted.', { position: 'bottom-right', diff --git a/packages/web/components/templates/article/PdfArticleContainer.tsx b/packages/web/components/templates/article/PdfArticleContainer.tsx index c1c69c80e..32713da06 100644 --- a/packages/web/components/templates/article/PdfArticleContainer.tsx +++ b/packages/web/components/templates/article/PdfArticleContainer.tsx @@ -10,9 +10,6 @@ import { isDarkTheme } from '../../../lib/themeUpdater' import PSPDFKit from 'pspdfkit' import { Instance, HighlightAnnotation, List, Annotation, Rect } from 'pspdfkit' import type { Highlight } from '../../../lib/networking/fragments/highlightFragment' -import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' -import { mergeHighlightMutation } from '../../../lib/networking/mutations/mergeHighlightMutation' import { pspdfKitKey } from '../../../lib/appConfig' import { HighlightNoteModal } from './HighlightNoteModal' import { showErrorToast } from '../../../lib/toastHelpers' @@ -24,6 +21,12 @@ import { NotebookHeader } from './NotebookHeader' import useWindowDimensions from '../../../lib/hooks/useGetWindowDimensions' import { ResizableSidebar } from './ResizableSidebar' import { DEFAULT_HOME_PATH } from '../../../lib/navigations' +import { + useCreateHighlight, + useDeleteHighlight, + useMergeHighlight, + useUpdateHighlight, +} from '../../../lib/networking/highlights/useItemHighlights' export type PdfArticleContainerProps = { viewer: UserBasicData @@ -42,6 +45,10 @@ export default function PdfArticleContainer( number | undefined >(undefined) const highlightsRef = useRef([]) + const createHighlight = useCreateHighlight() + const deleteHighlight = useDeleteHighlight() + const mergeHighlight = useMergeHighlight() + const updateHighlight = useUpdateHighlight() const updateItemReadStatus = useUpdateItemReadStatus() const annotationOmnivoreId = (annotation: Annotation): string | undefined => { @@ -117,7 +124,11 @@ export default function PdfArticleContainer( .delete(annotation) .then(() => { if (annotationId) { - return deleteHighlightMutation(props.article.id, annotationId) + return deleteHighlight.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + highlightId: annotationId, + }) } }) .then(() => { @@ -218,8 +229,6 @@ export default function PdfArticleContainer( }), } - console.log('instnace config: ', config) - instance = await PSPDFKit.load(config) console.log('created PDF instance', instance) @@ -233,7 +242,11 @@ export default function PdfArticleContainer( } const annotationId = annotationOmnivoreId(annotation) if (annotationId) { - await deleteHighlightMutation(props.article.id, annotationId) + await deleteHighlight.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + highlightId: annotationId, + }) } }) @@ -343,16 +356,21 @@ export default function PdfArticleContainer( if (overlapping.size === 0) { const positionPercent = positionPercentForAnnotation(annotation) - const result = await createHighlightMutation({ - id: id, - shortId: shortId, - quote: quote, - articleId: props.article.id, - prefix: surroundingText.prefix, - suffix: surroundingText.suffix, - patch: JSON.stringify(serialized), - highlightPositionPercent: positionPercent * 100, - highlightPositionAnchorIndex: annotation.pageIndex, + + const result = await createHighlight.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + input: { + id: id, + shortId: shortId, + quote: quote, + articleId: props.article.id, + prefix: surroundingText.prefix, + suffix: surroundingText.suffix, + patch: JSON.stringify(serialized), + highlightPositionPercent: positionPercent * 100, + highlightPositionAnchorIndex: annotation.pageIndex, + }, }) if (result) { highlightsRef.current.push(result) @@ -388,20 +406,24 @@ export default function PdfArticleContainer( (ha) => (ha.customData?.omnivoreHighlight as Highlight).id ) const positionPercent = positionPercentForAnnotation(annotation) - const result = await mergeHighlightMutation({ - quote, - id, - shortId, - patch: JSON.stringify(serialized), - prefix: surroundingText.prefix, - suffix: surroundingText.suffix, - articleId: props.article.id, - overlapHighlightIdList: mergedIds.toArray(), - highlightPositionPercent: positionPercent * 100, - highlightPositionAnchorIndex: annotation.pageIndex, + const result = await mergeHighlight.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + input: { + quote, + id, + shortId, + patch: JSON.stringify(serialized), + prefix: surroundingText.prefix, + suffix: surroundingText.suffix, + articleId: props.article.id, + overlapHighlightIdList: mergedIds.toArray(), + highlightPositionPercent: positionPercent * 100, + highlightPositionAnchorIndex: annotation.pageIndex, + }, }) - if (result) { - highlightsRef.current.push(result) + if (result && result.highlight) { + highlightsRef.current.push(result.highlight) } } } @@ -415,10 +437,14 @@ export default function PdfArticleContainer( Math.max(0, ((pageIndex + 1) / instance.totalPageCount) * 100) ) await updateItemReadStatus.mutateAsync({ - id: props.article.id, - force: true, - readingProgressPercent: percent, - readingProgressAnchorIndex: pageIndex, + itemId: props.article.id, + slug: props.article.slug, + input: { + id: props.article.id, + force: true, + readingProgressPercent: percent, + readingProgressAnchorIndex: pageIndex, + }, }) } ) @@ -521,7 +547,11 @@ export default function PdfArticleContainer( const storedId = annotationOmnivoreId(annotation) if (storedId == annotationId) { await instance.delete(annotation) - await deleteHighlightMutation(props.article.id, annotationId) + await deleteHighlight.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + highlightId: annotationId, + }) const highlightIdx = highlightsRef.current.findIndex((value) => { return value.id == annotationId @@ -586,8 +616,7 @@ export default function PdfArticleContainer( { const savedHighlight = highlightsRef.current.find( (other: Highlight) => { diff --git a/packages/web/components/templates/article/SetLabelsModalPresenter.tsx b/packages/web/components/templates/article/SetLabelsModalPresenter.tsx index 5fb68dd66..62a5f9307 100644 --- a/packages/web/components/templates/article/SetLabelsModalPresenter.tsx +++ b/packages/web/components/templates/article/SetLabelsModalPresenter.tsx @@ -4,21 +4,24 @@ import { LabelsProvider } from './SetLabelsControl' import { SetLabelsModal } from './SetLabelsModal' import { useSetHighlightLabels } from '../../../lib/hooks/useSetHighlightLabels' import { Highlight } from '../../../lib/networking/fragments/highlightFragment' +import { LibraryItemNode } from '../../../lib/networking/library_items/useLibraryItems' type SetPageLabelsModalPresenterProps = { - articleId: string - article: LabelsProvider + libraryItem: LibraryItemNode onOpenChange: (open: boolean) => void } export function SetPageLabelsModalPresenter( props: SetPageLabelsModalPresenterProps ): JSX.Element { - const [labels, dispatchLabels] = useSetPageLabels(props.articleId) + const [labels, dispatchLabels] = useSetPageLabels( + props.libraryItem.id, + props.libraryItem.slug + ) const onOpenChange = useCallback(() => { - if (props.article) { - props.article.labels = labels.labels + if (props.libraryItem) { + props.libraryItem.labels = labels.labels } props.onOpenChange(true) }, [props, labels]) @@ -26,13 +29,13 @@ export function SetPageLabelsModalPresenter( useEffect(() => { dispatchLabels({ type: 'RESET', - labels: props.article.labels ?? [], + labels: props.libraryItem.labels ?? [], }) - }, [props.article, dispatchLabels]) + }, [props.libraryItem, dispatchLabels]) return ( { ;(async () => { if (title !== '') { - const res = await updatePageMutation({ - pageId: props.item.node.id, - title, - description, - byline: author, - savedAt: savedAt.toISOString(), - publishedAt: publishedAt ? publishedAt.toISOString() : undefined, + const res = await updateItem.mutateAsync({ + itemId: props.item.node.id, + slug: props.item.node.slug, + input: { + pageId: props.item.node.id, + title, + description, + byline: author, + savedAt: savedAt.toISOString(), + publishedAt: publishedAt ? publishedAt.toISOString() : undefined, + }, }) if (res) { @@ -102,6 +110,7 @@ type EditArticleModalProps = { } export function EditArticleModal(props: EditArticleModalProps): JSX.Element { + const updateItem = useUpdateItem() const onSave = useCallback( ( title: string, @@ -112,13 +121,17 @@ export function EditArticleModal(props: EditArticleModalProps): JSX.Element { ) => { ;(async () => { if (title !== '') { - const res = await updatePageMutation({ - pageId: props.article.id, - title, - description, - byline: author, - savedAt: savedAt.toISOString(), - publishedAt: publishedAt ? publishedAt.toISOString() : undefined, + const res = await updateItem.mutateAsync({ + itemId: props.article.id, + slug: props.article.slug, + input: { + pageId: props.article.id, + title, + description, + byline: author, + savedAt: savedAt.toISOString(), + publishedAt: publishedAt ? publishedAt.toISOString() : undefined, + }, }) if (res) { props.updateArticle( diff --git a/packages/web/components/templates/library/LibraryContainer.tsx b/packages/web/components/templates/library/LibraryContainer.tsx index 223d60ad9..1661c2021 100644 --- a/packages/web/components/templates/library/LibraryContainer.tsx +++ b/packages/web/components/templates/library/LibraryContainer.tsx @@ -398,8 +398,12 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element { case 'unarchive': try { await archiveItem.mutateAsync({ - linkId: item.node.id, - archived: action == 'archive', + itemId: item.node.id, + slug: item.node.slug, + input: { + linkId: item.node.id, + archived: action == 'archive', + }, }) } catch (err) { console.log('Error setting archive state: ', err) @@ -414,7 +418,10 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element { break case 'delete': try { - await deleteItem.mutateAsync(item.node.id) + await deleteItem.mutateAsync({ + itemId: item.node.id, + slug: item.node.slug, + }) } catch (err) { console.log('Error deleting item: ', err) showErrorToast(`Error deleting item`, { @@ -443,9 +450,13 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element { } try { await updateItemReadStatus.mutateAsync({ - id: item.node.id, - force: true, - ...values, + itemId: item.node.id, + slug: item.node.slug, + input: { + id: item.node.id, + force: true, + ...values, + }, }) } catch (err) { console.log('Error marking item: ', err) @@ -459,6 +470,7 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element { try { await moveToFolder.mutateAsync({ itemId: item.node.id, + slug: item.node.slug, folder: 'inbox', }) } catch (err) { @@ -1250,8 +1262,7 @@ export function LibraryItemsLayout( )} {props.labelsTarget?.node.id && ( { if (props.labelsTarget) { const activate = props.labelsTarget diff --git a/packages/web/lib/hooks/useLibraryItemActions.tsx b/packages/web/lib/hooks/useLibraryItemActions.tsx index fce259c47..5d1f7234f 100644 --- a/packages/web/lib/hooks/useLibraryItemActions.tsx +++ b/packages/web/lib/hooks/useLibraryItemActions.tsx @@ -4,23 +4,27 @@ import { showSuccessToast, showSuccessToastWithUndo, } from '../toastHelpers' -import { updatePageMutation } from '../networking/mutations/updatePageMutation' -import { State } from '../networking/fragments/articleFragment' import { useArchiveItem, useDeleteItem, useMoveItemToFolder, + useRestoreItem, } from '../networking/library_items/useLibraryItems' export default function useLibraryItemActions() { const archiveItem = useArchiveItem() const deleteItem = useDeleteItem() const moveItem = useMoveItemToFolder() + const restoreItem = useRestoreItem() - const doArchiveItem = useCallback(async (itemId: string) => { + const doArchiveItem = useCallback(async (itemId: string, slug: string) => { const result = await archiveItem.mutateAsync({ - linkId: itemId, - archived: true, + itemId: itemId, + slug: slug, + input: { + linkId: itemId, + archived: true, + }, }) console.log('result: ', result) @@ -33,33 +37,37 @@ export default function useLibraryItemActions() { return !!result }, []) - const doDeleteItem = useCallback(async (itemId: string, undo: () => void) => { - const result = await deleteItem.mutateAsync(itemId) + const doDeleteItem = useCallback( + async (itemId: string, slug: string, undo: () => void) => { + const result = await deleteItem.mutateAsync({ itemId, slug }) - if (result) { - showSuccessToastWithUndo('Item removed', async () => { - const result = await updatePageMutation({ - pageId: itemId, - state: State.SUCCEEDED, + if (result) { + showSuccessToastWithUndo('Item removed', async () => { + const result = await restoreItem.mutateAsync({ itemId, slug }) + + undo() + + if (result) { + showSuccessToast('Item recovered') + } else { + showErrorToast('Error recovering, check your deleted items') + } }) + } else { + showErrorToast('Error removing item', { position: 'bottom-right' }) + } - undo() + return !!result + }, + [] + ) - if (result) { - showSuccessToast('Item recovered') - } else { - showErrorToast('Error recovering, check your deleted items') - } - }) - } else { - showErrorToast('Error removing item', { position: 'bottom-right' }) - } - - return !!result - }, []) - - const doMoveItem = useCallback(async (itemId: string) => { - const result = await moveItem.mutateAsync({ itemId, folder: 'inbox' }) + const doMoveItem = useCallback(async (itemId: string, slug: string) => { + const result = await moveItem.mutateAsync({ + itemId, + slug, + folder: 'inbox', + }) if (result) { showSuccessToast('Moved to library', { position: 'bottom-right' }) } else { diff --git a/packages/web/lib/hooks/useSetPageLabels.tsx b/packages/web/lib/hooks/useSetPageLabels.tsx index b1216f138..06982fafd 100644 --- a/packages/web/lib/hooks/useSetPageLabels.tsx +++ b/packages/web/lib/hooks/useSetPageLabels.tsx @@ -11,7 +11,8 @@ export type LabelsDispatcher = (action: { }) => void export const useSetPageLabels = ( - articleId?: string + libraryItemId?: string, + libraryItemSlug?: string ): [{ labels: Label[] }, LabelsDispatcher] => { const setItemLabels = useSetItemLabels() const saveLabels = (labels: Label[], articleId: string) => { @@ -19,6 +20,7 @@ export const useSetPageLabels = ( if (articleId) { const result = await setItemLabels.mutateAsync({ itemId: articleId, + slug: libraryItemSlug, labels, }) if (!result) { @@ -91,13 +93,13 @@ export const useSetPageLabels = ( dispatchLabels({ type: 'UPDATE_ARTICLE_ID', labels: [], - articleId: articleId, + articleId: libraryItemId, }) - }, [articleId]) + }, [libraryItemId]) const [labels, dispatchLabels] = useReducer(labelsReducer, { labels: [], - articleId: articleId, + articleId: libraryItemId, throttledSave: debouncedSave, }) diff --git a/packages/web/lib/networking/highlights/useItemHighlights.tsx b/packages/web/lib/networking/highlights/useItemHighlights.tsx index da62088ef..8058ffdf2 100644 --- a/packages/web/lib/networking/highlights/useItemHighlights.tsx +++ b/packages/web/lib/networking/highlights/useItemHighlights.tsx @@ -15,6 +15,7 @@ export const useCreateHighlight = () => { const queryClient = useQueryClient() const createHighlight = async (variables: { itemId: string + slug: string | undefined input: CreateHighlightInput }) => { const result = (await gqlFetcher(GQL_CREATE_HIGHLIGHT, { @@ -29,12 +30,17 @@ export const useCreateHighlight = () => { mutationFn: createHighlight, onSuccess: (newHighlight, variables) => { if (newHighlight) { - updateItemProperty(queryClient, variables.itemId, (item) => { - return { - ...item, - highlights: [...item.highlights, newHighlight], + updateItemProperty( + queryClient, + variables.itemId, + variables.slug, + (item) => { + return { + ...item, + highlights: [...item.highlights, newHighlight], + } } - }) + ) } }, }) @@ -44,6 +50,7 @@ export const useDeleteHighlight = () => { const queryClient = useQueryClient() const deleteHighlight = async (variables: { itemId: string + slug: string highlightId: string }) => { const result = (await gqlFetcher(GQL_DELETE_HIGHLIGHT, { @@ -58,14 +65,19 @@ export const useDeleteHighlight = () => { mutationFn: deleteHighlight, onSuccess: (deletedHighlight, variables) => { if (deletedHighlight) { - updateItemProperty(queryClient, variables.itemId, (item) => { - return { - ...item, - highlights: item.highlights.filter( - (h) => h.id != deletedHighlight.id - ), + updateItemProperty( + queryClient, + variables.itemId, + variables.slug, + (item) => { + return { + ...item, + highlights: item.highlights.filter( + (h) => h.id != deletedHighlight.id + ), + } } - }) + ) } }, }) @@ -75,6 +87,7 @@ export const useUpdateHighlight = () => { const queryClient = useQueryClient() const updateHighlight = async (variables: { itemId: string + slug: string | undefined input: UpdateHighlightInput }) => { const result = (await gqlFetcher(GQL_UPDATE_HIGHLIGHT, { @@ -89,15 +102,20 @@ export const useUpdateHighlight = () => { mutationFn: updateHighlight, onSuccess: (updatedHighlight, variables) => { if (updatedHighlight) { - updateItemProperty(queryClient, variables.itemId, (item) => { - return { - ...item, - highlights: [ - ...item.highlights.filter((h) => h.id != updatedHighlight.id), - updatedHighlight, - ], + updateItemProperty( + queryClient, + variables.itemId, + variables.slug, + (item) => { + return { + ...item, + highlights: [ + ...item.highlights.filter((h) => h.id != updatedHighlight.id), + updatedHighlight, + ], + } } - }) + ) } }, }) @@ -107,6 +125,7 @@ export const useMergeHighlight = () => { const queryClient = useQueryClient() const mergeHighlight = async (variables: { itemId: string + slug: string input: MergeHighlightInput }) => { const result = (await gqlFetcher(GQL_MERGE_HIGHLIGHT, { @@ -137,15 +156,20 @@ export const useMergeHighlight = () => { if (mergeHighlights && mergeHighlights.highlight) { const newHighlight = mergeHighlights.highlight const mergedIds = mergeHighlights.overlapHighlightIdList ?? [] - updateItemProperty(queryClient, variables.itemId, (item) => { - return { - ...item, - highlights: [ - ...item.highlights.filter((h) => mergedIds.indexOf(h.id) == -1), - newHighlight, - ], + updateItemProperty( + queryClient, + variables.itemId, + variables.slug, + (item) => { + return { + ...item, + highlights: [ + ...item.highlights.filter((h) => mergedIds.indexOf(h.id) == -1), + newHighlight, + ], + } } - }) + ) } }, }) diff --git a/packages/web/lib/networking/library_items/useLibraryItems.tsx b/packages/web/lib/networking/library_items/useLibraryItems.tsx index 5ab6dae0b..ec3b99cad 100644 --- a/packages/web/lib/networking/library_items/useLibraryItems.tsx +++ b/packages/web/lib/networking/library_items/useLibraryItems.tsx @@ -43,9 +43,10 @@ function gqlFetcher( const updateItemStateInCache = ( queryClient: QueryClient, itemId: string, + slug: string | undefined, newState: State ) => { - updateItemPropertyInCache(queryClient, itemId, 'state', newState) + updateItemPropertyInCache(queryClient, itemId, slug, 'state', newState) } function createDictionary( @@ -59,10 +60,11 @@ function createDictionary( const updateItemPropertyInCache = ( queryClient: QueryClient, itemId: string, + slug: string | undefined, propertyName: string, propertyValue: any ) => { - updateItemProperty(queryClient, itemId, (oldItem) => { + updateItemProperty(queryClient, itemId, slug, (oldItem) => { const setter = createDictionary(propertyName, propertyValue) return { ...oldItem, @@ -74,12 +76,15 @@ const updateItemPropertyInCache = ( export const updateItemProperty = ( queryClient: QueryClient, itemId: string, + slug: string | undefined, updateFunc: (input: ArticleAttributes) => ArticleAttributes ) => { let foundItemSlug: string | undefined const keys = queryClient .getQueryCache() .findAll({ queryKey: ['libraryItems'] }) + console.log('updateItemProperty::KEYS: ', keys) + keys.forEach((query) => { queryClient.setQueryData(query.queryKey, (data: any) => { if (!data) return data @@ -101,9 +106,9 @@ export const updateItemProperty = ( } return updatedData }) - if (foundItemSlug) + if (foundItemSlug || slug) queryClient.setQueryData( - ['libraryItem', foundItemSlug], + ['libraryItem', foundItemSlug ?? slug], (oldData: ArticleAttributes) => { return { ...oldData, @@ -114,29 +119,66 @@ export const updateItemProperty = ( }) } -const updateItemPropertiesInCache = ( +const overwriteItemPropertiesInCache = ( queryClient: QueryClient, itemId: string, - item: ArticleAttributes + slug: string | undefined, + item: any ) => { + let foundItemSlug: string | undefined const keys = queryClient .getQueryCache() .findAll({ queryKey: ['libraryItems'] }) + console.log('overwriteItemPropertiesInCache::KEYS: ', keys) + // keys.forEach((query) => { + // queryClient.setQueryData(query.queryKey, (data: any) => { + // if (!data) return data + // return { + // ...data, + // pages: data.pages.map((page: any) => ({ + // ...page, + // edges: page.edges.map((edge: any) => + // edge.node.id === itemId + // ? { ...edge, node: { ...edge.node, ...item } } + // : edge + // ), + // })), + // } + // }) + // }) keys.forEach((query) => { queryClient.setQueryData(query.queryKey, (data: any) => { + console.log('query.queryKey', query.queryKey, data) if (!data) return data - return { + const updatedData = { ...data, pages: data.pages.map((page: any) => ({ ...page, - edges: page.edges.map((edge: any) => - edge.node.id === itemId - ? { ...edge, node: { ...edge.node, ...item } } - : edge - ), + edges: page.edges.map((edge: any) => { + if (edge.node.id === itemId) { + foundItemSlug = edge.node.slug + return { + ...edge, + node: { ...edge.node, ...item }, + } + } + return edge + }), })), } + return updatedData }) + console.log('updating foundItem slug: ', foundItemSlug) + if (foundItemSlug || slug) + queryClient.setQueryData( + ['libraryItem', foundItemSlug ?? slug], + (oldData: ArticleAttributes) => { + return { + ...oldData, + ...item, + } + } + ) }) } @@ -172,9 +214,13 @@ export function useGetLibraryItems( export const useArchiveItem = () => { const queryClient = useQueryClient() - const archiveItem = async (input: SetLinkArchivedInput) => { + const archiveItem = async (variables: { + itemId: string + slug: string + input: SetLinkArchivedInput + }) => { const result = (await gqlFetcher(GQL_SET_LINK_ARCHIVED, { - input, + input: variables.input, })) as SetLinkArchivedData if (result.errorCodes?.length) { throw new Error(result.errorCodes[0]) @@ -183,13 +229,18 @@ export const useArchiveItem = () => { } return useMutation({ mutationFn: archiveItem, - onMutate: async (input: SetLinkArchivedInput) => { + onMutate: async (variables: { + itemId: string + slug: string + input: SetLinkArchivedInput + }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) updateItemStateInCache( queryClient, - input.linkId, - input.archived ? State.ARCHIVED : State.SUCCEEDED + variables.itemId, + variables.slug, + variables.input.archived ? State.ARCHIVED : State.SUCCEEDED ) return { previousItems: queryClient.getQueryData(['libraryItems']) } @@ -209,9 +260,9 @@ export const useArchiveItem = () => { export const useDeleteItem = () => { const queryClient = useQueryClient() - const deleteItem = async (itemId: string) => { + const deleteItem = async (variables: { itemId: string; slug: string }) => { const result = (await gqlFetcher(GQL_DELETE_LIBRARY_ITEM, { - input: { articleID: itemId, bookmark: false }, + input: { articleID: variables.itemId, bookmark: false }, })) as SetBookmarkArticleData if (result.setBookmarkArticle.errorCodes?.length) { throw new Error(result.setBookmarkArticle.errorCodes[0]) @@ -220,11 +271,16 @@ export const useDeleteItem = () => { } return useMutation({ mutationFn: deleteItem, - onMutate: async (itemId: string) => { + onMutate: async (variables: { itemId: string; slug: string }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'], }) - updateItemStateInCache(queryClient, itemId, State.DELETED) + updateItemStateInCache( + queryClient, + variables.itemId, + variables.slug, + State.DELETED + ) return { previousItems: queryClient.getQueryData(['libraryItems']) } }, onError: (error, itemId, context) => { @@ -242,9 +298,9 @@ export const useDeleteItem = () => { export const useRestoreItem = () => { const queryClient = useQueryClient() - const restoreItem = async (itemId: string) => { + const restoreItem = async (variables: { itemId: string; slug: string }) => { const result = (await gqlFetcher(GQL_UPDATE_LIBRARY_ITEM, { - input: { pageId: itemId, state: State.SUCCEEDED }, + input: { pageId: variables.itemId, state: State.SUCCEEDED }, })) as UpdateLibraryItemData if (result.updatePage.errorCodes?.length) { throw new Error(result.updatePage.errorCodes[0]) @@ -253,9 +309,59 @@ export const useRestoreItem = () => { } return useMutation({ mutationFn: restoreItem, - onMutate: async (itemId: string) => { + onMutate: async (variables: { itemId: string; slug: string }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) - updateItemStateInCache(queryClient, itemId, State.SUCCEEDED) + updateItemStateInCache( + queryClient, + variables.itemId, + variables.slug, + State.SUCCEEDED + ) + return { previousItems: queryClient.getQueryData(['libraryItems']) } + }, + onError: (error, itemId, context) => { + if (context?.previousItems) { + queryClient.setQueryData(['libraryItems'], context.previousItems) + } + }, + onSettled: async () => { + await queryClient.invalidateQueries({ + queryKey: ['libraryItems'], + }) + }, + }) +} + +export const useUpdateItem = () => { + const queryClient = useQueryClient() + const updateItem = async (variables: { + itemId: string + slug: string | undefined + input: UpdateLibraryItemInput + }) => { + const result = (await gqlFetcher(GQL_UPDATE_LIBRARY_ITEM, { + input: variables.input, + })) as UpdateLibraryItemData + if (result.updatePage.errorCodes?.length) { + throw new Error(result.updatePage.errorCodes[0]) + } + return result.updatePage + } + return useMutation({ + mutationFn: updateItem, + onMutate: async (variables: { + itemId: string + slug: string | undefined + input: UpdateLibraryItemInput + }) => { + await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) + console.log('will update item') + overwriteItemPropertiesInCache( + queryClient, + variables.itemId, + variables.slug, + variables.input + ) return { previousItems: queryClient.getQueryData(['libraryItems']) } }, onError: (error, itemId, context) => { @@ -273,11 +379,13 @@ export const useRestoreItem = () => { export const useUpdateItemReadStatus = () => { const queryClient = useQueryClient() - const updateItemReadStatus = async ( + const updateItemReadStatus = async (variables: { + itemId: string + slug: string input: ArticleReadingProgressMutationInput - ) => { + }) => { const result = (await gqlFetcher(GQL_SAVE_ARTICLE_READING_PROGRESS, { - input, + input: variables.input, })) as ArticleReadingProgressMutationData if (result.saveArticleReadingProgress.errorCodes?.length) { throw new Error(result.saveArticleReadingProgress.errorCodes[0]) @@ -286,13 +394,18 @@ export const useUpdateItemReadStatus = () => { } return useMutation({ mutationFn: updateItemReadStatus, - onMutate: async (input: ArticleReadingProgressMutationInput) => { + onMutate: async (variables: { + itemId: string + slug: string + input: ArticleReadingProgressMutationInput + }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) updateItemPropertyInCache( queryClient, - input.id, + variables.itemId, + variables.slug, 'readingProgressPercent', - input.readingProgressPercent + variables.input.readingProgressPercent ) return { previousItems: queryClient.getQueryData(['libraryItems']) } }, @@ -305,7 +418,8 @@ export const useUpdateItemReadStatus = () => { if (data) { updateItemPropertyInCache( queryClient, - data.id, + variables.itemId, + variables.slug, 'readingProgressPercent', data.readingProgressPercent ) @@ -329,7 +443,12 @@ export const useGetLibraryItemContent = (username: string, slug: string) => { } const article = response.article.article if (article) { - updateItemPropertiesInCache(queryClient, article.id, article) + overwriteItemPropertiesInCache( + queryClient, + article.id, + article.slug, + article + ) } return response.article.article }, @@ -338,7 +457,11 @@ export const useGetLibraryItemContent = (username: string, slug: string) => { export const useMoveItemToFolder = () => { const queryClient = useQueryClient() - const moveItem = async (variables: { itemId: string; folder: string }) => { + const moveItem = async (variables: { + itemId: string + slug: string | undefined + folder: string + }) => { const result = (await gqlFetcher(GQL_MOVE_ITEM_TO_FOLDER, { id: variables.itemId, folder: variables.folder, @@ -350,11 +473,16 @@ export const useMoveItemToFolder = () => { } return useMutation({ mutationFn: moveItem, - onMutate: async (variables: { itemId: string; folder: string }) => { + onMutate: async (variables: { + itemId: string + slug: string | undefined + folder: string + }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) updateItemPropertyInCache( queryClient, variables.itemId, + variables.slug, 'folder', variables.folder ) @@ -375,7 +503,11 @@ export const useMoveItemToFolder = () => { export const useSetItemLabels = () => { const queryClient = useQueryClient() - const setLabels = async (variables: { itemId: string; labels: Label[] }) => { + const setLabels = async (variables: { + itemId: string + slug: string | undefined + labels: Label[] + }) => { const labelIds = variables.labels.map((l) => l.id) const result = (await gqlFetcher(GQL_SET_LABELS, { input: { pageId: variables.itemId, labelIds }, @@ -387,11 +519,16 @@ export const useSetItemLabels = () => { } return useMutation({ mutationFn: setLabels, - onMutate: async (variables: { itemId: string; labels: Label[] }) => { + onMutate: async (variables: { + itemId: string + slug: string | undefined + labels: Label[] + }) => { await queryClient.cancelQueries({ queryKey: ['libraryItems'] }) updateItemPropertyInCache( queryClient, variables.itemId, + variables.slug, 'labels', variables.labels ) @@ -406,6 +543,7 @@ export const useSetItemLabels = () => { updateItemPropertyInCache( queryClient, variables.itemId, + variables.slug, 'labels', newLabels ) @@ -418,6 +556,16 @@ export const useSetItemLabels = () => { }) } +type UpdateLibraryItemInput = { + pageId: string + title?: string + byline?: string | undefined + description?: string + savedAt?: string + publishedAt?: string + state?: State +} + type SetLabelsData = { setLabels: SetLabelsResult } diff --git a/packages/web/lib/networking/mutations/createHighlightMutation.ts b/packages/web/lib/networking/mutations/createHighlightMutation.ts deleted file mode 100644 index 703f2bfd2..000000000 --- a/packages/web/lib/networking/mutations/createHighlightMutation.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { gql } from 'graphql-request' -import { gqlFetcher } from '../networkHelpers' -import { - Highlight, - highlightFragment, - HighlightType, -} from './../fragments/highlightFragment' -import { CreateHighlightInput } from '../highlights/useItemHighlights' - -type CreateHighlightOutput = { - createHighlight: InnerCreateHighlightOutput -} - -type InnerCreateHighlightOutput = { - highlight: Highlight -} - -export async function createHighlightMutation( - input: CreateHighlightInput -): Promise { - const mutation = gql` - mutation CreateHighlight($input: CreateHighlightInput!) { - createHighlight(input: $input) { - ... on CreateHighlightSuccess { - highlight { - ...HighlightFields - } - } - - ... on CreateHighlightError { - errorCodes - } - } - } - ${highlightFragment} - ` - - try { - const data = await gqlFetcher(mutation, { input }) - const output = data as CreateHighlightOutput | undefined - return output?.createHighlight.highlight - } catch { - return undefined - } -} diff --git a/packages/web/lib/networking/mutations/shareHighlightToFeedMutation.ts b/packages/web/lib/networking/mutations/shareHighlightToFeedMutation.ts deleted file mode 100644 index 1e502a1fa..000000000 --- a/packages/web/lib/networking/mutations/shareHighlightToFeedMutation.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { gql } from 'graphql-request' -import { gqlFetcher } from '../networkHelpers' - -type ShareHighlightToFeedMutationInput = { - id: string - share: boolean -} - -export async function shareHighlightToFeedMutation( - input: ShareHighlightToFeedMutationInput -): Promise { - const mutation = gql` - mutation SetShareHighlight($input: SetShareHighlightInput!) { - setShareHighlight(input: $input) { - ... on SetShareHighlightSuccess { - highlight { - id - } - } - ... on SetShareHighlightError { - errorCodes - } - } - } - ` - - try { - await gqlFetcher(mutation, { input }) - return true - } catch { - return false - } -} diff --git a/packages/web/pages/[username]/[slug]/index.tsx b/packages/web/pages/[username]/[slug]/index.tsx index e85bec618..90107e997 100644 --- a/packages/web/pages/[username]/[slug]/index.tsx +++ b/packages/web/pages/[username]/[slug]/index.tsx @@ -11,10 +11,6 @@ import { PdfArticleContainerProps } from './../../../components/templates/articl import { useCallback, useEffect, useState } from 'react' import dynamic from 'next/dynamic' import { Toaster } from 'react-hot-toast' -import { createHighlightMutation } from '../../../lib/networking/mutations/createHighlightMutation' -import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' -import { mergeHighlightMutation } from '../../../lib/networking/mutations/mergeHighlightMutation' -import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation' import Script from 'next/script' import { ArticleActionsMenu } from '../../../components/templates/article/ArticleActionsMenu' import { Label } from '../../../lib/networking/fragments/labelFragment' @@ -130,8 +126,12 @@ export default function Reader(): JSX.Element { case 'unarchive': try { await archiveItem.mutateAsync({ - linkId: libraryItem.id, - archived: action == 'archive', + itemId: libraryItem.id, + slug: libraryItem.slug, + input: { + linkId: libraryItem.id, + archived: action == 'archive', + }, }) } catch { showErrorToast(`Error ${action}ing item`, { @@ -161,9 +161,13 @@ export default function Reader(): JSX.Element { } try { await updateItemReadStatus.mutateAsync({ - id: libraryItem.id, - force: true, - ...values, + itemId: libraryItem.id, + slug: libraryItem.slug, + input: { + id: libraryItem.id, + force: true, + ...values, + }, }) } catch { showErrorToast(`Error marking as ${desc}`, { @@ -175,7 +179,10 @@ export default function Reader(): JSX.Element { break case 'delete': try { - await deleteItem.mutateAsync(libraryItem.id) + await deleteItem.mutateAsync({ + itemId: libraryItem.id, + slug: libraryItem.slug, + }) } catch { showErrorToast(`Error deleting item`, { position: 'bottom-right', @@ -457,7 +464,10 @@ export default function Reader(): JSX.Element { [readerSettings, showHighlightsModal] ) - const [labels, dispatchLabels] = useSetPageLabels(libraryItem?.id) + const [labels, dispatchLabels] = useSetPageLabels( + libraryItem?.id, + libraryItem?.slug + ) new Error() if ( @@ -590,6 +600,7 @@ export default function Reader(): JSX.Element { try { const result = await createHighlight.mutateAsync({ itemId: libraryItem.id, + slug: libraryItem.slug, input, }) return result @@ -605,6 +616,7 @@ export default function Reader(): JSX.Element { try { await deleteHighlight.mutateAsync({ itemId: libraryItem.id, + slug: libraryItem.slug, highlightId, }) return true @@ -617,6 +629,7 @@ export default function Reader(): JSX.Element { try { const result = await mergeHighlight.mutateAsync({ itemId: libraryItem.id, + slug: libraryItem.slug, input, }) return result?.highlight @@ -629,6 +642,7 @@ export default function Reader(): JSX.Element { try { const result = await updateHighlight.mutateAsync({ itemId: libraryItem.id, + slug: libraryItem.slug, input, }) return result?.id @@ -641,7 +655,11 @@ export default function Reader(): JSX.Element { input: ArticleReadingProgressMutationInput ) => { try { - await updateItemReadStatus.mutateAsync(input) + await updateItemReadStatus.mutateAsync({ + itemId: libraryItem.id, + slug: libraryItem.slug, + input, + }) } catch { return false } @@ -722,15 +740,14 @@ export default function Reader(): JSX.Element { article={libraryItem} onOpenChange={() => setShowEditModal(false)} updateArticle={(title, author, description, savedAt, publishedAt) => { - libraryItem.title = title - libraryItem.author = author - libraryItem.description = description - libraryItem.savedAt = savedAt - libraryItem.publishedAt = publishedAt - - const titleEvent = new Event('updateTitle') as UpdateTitleEvent - titleEvent.title = title - document.dispatchEvent(titleEvent) + // libraryItem.title = title + // libraryItem.author = author + // libraryItem.description = description + // libraryItem.savedAt = savedAt + // libraryItem.publishedAt = publishedAt + // const titleEvent = new Event('updateTitle') as UpdateTitleEvent + // titleEvent.title = title + // document.dispatchEvent(titleEvent) }} /> )}