mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Better handling of slugs and library item lists in the cache
This commit is contained in:
parent
17e547b95e
commit
6c6cc8d4c4
20 changed files with 538 additions and 391 deletions
|
|
@ -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 | string>(undefined)
|
||||
const [labelsTarget, setLabelsTarget] =
|
||||
useState<Highlight | undefined>(undefined)
|
||||
const [labelsTarget, setLabelsTarget] = useState<Highlight | undefined>(
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}}
|
||||
>
|
||||
<AddToLibraryActionIcon />
|
||||
|
|
@ -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)
|
||||
}}
|
||||
>
|
||||
<ArchiveActionIcon />
|
||||
|
|
@ -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)
|
||||
}}
|
||||
>
|
||||
<RemoveActionIcon />
|
||||
|
|
|
|||
|
|
@ -69,9 +69,13 @@ export function CardMenu(props: CardMenuProps): JSX.Element {
|
|||
<DropdownOption
|
||||
onSelect={async () => {
|
||||
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 {
|
|||
<DropdownOption
|
||||
onSelect={async () => {
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
<div ></div> */}
|
||||
</Box>
|
||||
{noteTarget && (
|
||||
<HighlightNoteModal
|
||||
highlight={noteTarget}
|
||||
libraryItemId={props.article.id}
|
||||
author={props.article.author ?? ''}
|
||||
title={props.article.title}
|
||||
onUpdate={(highlight: Highlight) => {
|
||||
const savedHighlight = highlightsRef.current.find(
|
||||
(other: Highlight) => {
|
||||
return other.id == highlight.id
|
||||
}
|
||||
)
|
||||
|
||||
if (savedHighlight) {
|
||||
savedHighlight.annotation = highlight.annotation
|
||||
}
|
||||
}}
|
||||
onOpenChange={() => {
|
||||
setNoteTarget(undefined)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{props.showHighlightsModal && (
|
||||
<NotebookModal
|
||||
key={notebookKey}
|
||||
viewer={props.viewer}
|
||||
item={props.article}
|
||||
onClose={(updatedHighlights, deletedAnnotations) => {
|
||||
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)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Highlight | undefined>
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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' && (
|
||||
<HighlightNoteModal
|
||||
highlight={highlightModalAction.highlight}
|
||||
author={props.articleAuthor}
|
||||
title={props.articleTitle}
|
||||
libraryItemId={props.articleId}
|
||||
libraryItemId={props.item.id}
|
||||
libraryItemSlug={props.item.slug}
|
||||
onUpdate={updateHighlightsCallback}
|
||||
onOpenChange={() =>
|
||||
setHighlightModalAction({ highlightModalAction: 'none' })
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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<Highlight[]>([])
|
||||
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(
|
|||
<HighlightNoteModal
|
||||
highlight={noteTarget}
|
||||
libraryItemId={props.article.id}
|
||||
author={props.article.author ?? ''}
|
||||
title={props.article.title}
|
||||
libraryItemSlug={props.article.slug}
|
||||
onUpdate={(highlight: Highlight) => {
|
||||
const savedHighlight = highlightsRef.current.find(
|
||||
(other: Highlight) => {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<SetLabelsModal
|
||||
provider={props.article}
|
||||
provider={props.libraryItem}
|
||||
selectedLabels={labels.labels}
|
||||
dispatchLabels={dispatchLabels}
|
||||
onOpenChange={onOpenChange}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import dayjs, { Dayjs } from 'dayjs'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { updatePageMutation } from '../../../lib/networking/mutations/updatePageMutation'
|
||||
import { ArticleAttributes } from '../../../lib/networking/library_items/useLibraryItems'
|
||||
import {
|
||||
ArticleAttributes,
|
||||
useUpdateItem,
|
||||
} from '../../../lib/networking/library_items/useLibraryItems'
|
||||
import { LibraryItem } from '../../../lib/networking/library_items/useLibraryItems'
|
||||
import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers'
|
||||
import { CloseButton } from '../../elements/CloseButton'
|
||||
|
|
@ -24,6 +27,7 @@ type EditLibraryItemModalProps = {
|
|||
export function EditLibraryItemModal(
|
||||
props: EditLibraryItemModalProps
|
||||
): JSX.Element {
|
||||
const updateItem = useUpdateItem()
|
||||
const onSave = useCallback(
|
||||
(
|
||||
title: string,
|
||||
|
|
@ -34,13 +38,17 @@ export function EditLibraryItemModal(
|
|||
) => {
|
||||
;(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(
|
||||
|
|
|
|||
|
|
@ -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 && (
|
||||
<SetPageLabelsModalPresenter
|
||||
articleId={props.labelsTarget.node.id}
|
||||
article={props.labelsTarget.node}
|
||||
libraryItem={props.labelsTarget.node}
|
||||
onOpenChange={() => {
|
||||
if (props.labelsTarget) {
|
||||
const activate = props.labelsTarget
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Highlight | undefined> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -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<boolean> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue