More moves to react-query for key library functions

This commit is contained in:
Jackson Harper
2024-07-29 17:30:47 +08:00
parent 457d1d9de9
commit 137283db0a
33 changed files with 697 additions and 755 deletions

View File

@ -8,7 +8,6 @@ import React from 'react'
export function ConfusedSlothIcon(): JSX.Element {
const { currentThemeIsDark } = useCurrentTheme()
console.log('is dark mdoe: ', currentThemeIsDark)
return currentThemeIsDark ? (
<ConfusedSlothIconDark />
) : (

View File

@ -80,6 +80,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
const saveText = useCallback(
(text: string) => {
;(async () => {
console.log('saving text: ', text)
const success = await updateHighlightMutation({
annotation: text,
libraryItemId: props.targetId,

View File

@ -50,6 +50,7 @@ export function HighlightViewNote(props: HighlightViewNoteProps): JSX.Element {
const saveText = useCallback(
(text: string, updateTime: Date, interactive: boolean) => {
;(async () => {
console.log('updating highlight text')
const success = await updateHighlightMutation({
annotation: text,
libraryItemId: props.targetId,

View File

@ -4,7 +4,7 @@ import {
DropdownOption,
DropdownSeparator,
} from '../elements/DropdownElements'
import { ArticleAttributes } from '../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } from '../../lib/networking/library_items/useLibraryItems'
import { State } from '../../lib/networking/fragments/articleFragment'
type DropdownMenuProps = {

View File

@ -1,5 +1,5 @@
import { Separator } from '@radix-ui/react-separator'
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } from '../../../lib/networking/library_items/useLibraryItems'
import { Button } from '../../elements/Button'
import { Box, SpanBox } from '../../elements/LayoutPrimitives'
import { styled, theme } from '../../tokens/stitches.config'

View File

@ -1,7 +1,3 @@
import {
ArticleAttributes,
TextDirection,
} from '../../../lib/networking/queries/useGetArticleQuery'
import { Article } from './../../../components/templates/article/Article'
import { Box, HStack, SpanBox, VStack } from './../../elements/LayoutPrimitives'
import { StyledText } from './../../elements/StyledText'
@ -19,11 +15,13 @@ import { updateTheme, updateThemeLocally } from '../../../lib/themeUpdater'
import { ArticleMutations } from '../../../lib/articleActions'
import { LabelChip } from '../../elements/LabelChip'
import { Label } from '../../../lib/networking/fragments/labelFragment'
import { Recommendation } from '../../../lib/networking/library_items/useLibraryItems'
import {
ArticleAttributes,
Recommendation,
TextDirection,
} from '../../../lib/networking/library_items/useLibraryItems'
import { Avatar } from '../../elements/Avatar'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { AISummary } from './AISummary'
import { userHasFeature } from '../../../lib/featureFlag'
type ArticleContainerProps = {
viewer: UserBasicData

View File

@ -1,4 +1,4 @@
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } from '../../../lib/networking/library_items/useLibraryItems'
import { Box, VStack } from '../../elements/LayoutPrimitives'
import { v4 as uuidv4 } from 'uuid'
import { nanoid } from 'nanoid'
@ -42,13 +42,15 @@ type EpubPatch = {
export default function EpubContainer(props: EpubContainerProps): JSX.Element {
const epubRef = useRef<HTMLDivElement | null>(null)
const renditionRef = useRef<Rendition | undefined>(undefined)
const [shareTarget, setShareTarget] =
useState<Highlight | undefined>(undefined)
const [shareTarget, setShareTarget] = useState<Highlight | undefined>(
undefined
)
const [touchStart, setTouchStart] = useState(0)
const [notebookKey, setNotebookKey] = useState<string>(uuidv4())
const [noteTarget, setNoteTarget] = useState<Highlight | undefined>(undefined)
const [noteTargetPageIndex, setNoteTargetPageIndex] =
useState<number | undefined>(undefined)
const [noteTargetPageIndex, setNoteTargetPageIndex] = useState<
number | undefined
>(undefined)
const highlightsRef = useRef<Highlight[]>([])
const book = useMemo(() => {

View File

@ -9,8 +9,8 @@ import { VStack } from '../../elements/LayoutPrimitives'
import { Highlight } from '../../../lib/networking/fragments/highlightFragment'
import { useCallback, useState } from 'react'
import { StyledTextArea } from '../../elements/StyledTextArea'
import { updateHighlightMutation } from '../../../lib/networking/mutations/updateHighlightMutation'
import { showErrorToast } from '../../../lib/toastHelpers'
import { useUpdateHighlight } from '../../../lib/networking/highlights/useItemHighlights'
type HighlightNoteModalProps = {
author: string
@ -25,6 +25,7 @@ type HighlightNoteModalProps = {
export function HighlightNoteModal(
props: HighlightNoteModalProps
): JSX.Element {
const updateHighlight = useUpdateHighlight()
const [noteContent, setNoteContent] = useState(
props.highlight?.annotation ?? ''
)
@ -38,20 +39,24 @@ export function HighlightNoteModal(
const saveNoteChanges = useCallback(async () => {
if (noteContent != props.highlight?.annotation && props.highlight?.id) {
const result = await updateHighlightMutation({
libraryItemId: props.libraryItemId,
highlightId: props.highlight?.id,
annotation: noteContent,
color: props.highlight?.color,
})
if (result) {
console.log('updating highlight textsdsdfsd')
try {
const result = await updateHighlight.mutateAsync({
itemId: props.libraryItemId,
input: {
libraryItemId: props.libraryItemId,
highlightId: props.highlight?.id,
annotation: noteContent,
color: props.highlight?.color,
},
})
props.onUpdate({ ...props.highlight, annotation: noteContent })
props.onOpenChange(false)
} else {
return result?.id
} catch (err) {
showErrorToast('Error updating your note', { position: 'bottom-right' })
return undefined
}
document.dispatchEvent(new Event('highlightsUpdated'))
}
if (!props.highlight && props.createHighlightForNote) {
const result = await props.createHighlightForNote(noteContent)

View File

@ -16,10 +16,10 @@ import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery
import { ReadableItem } from '../../../lib/networking/library_items/useLibraryItems'
import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
import { ArticleNotes } from '../../patterns/ArticleNotes'
import { useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery'
import { formattedShortTime } from '../../../lib/dateFormatting'
import { isDarkTheme } from '../../../lib/themeUpdater'
import { sortHighlights } from '../../../lib/highlights/sortHighlights'
import { useGetLibraryItemContent } from '../../../lib/networking/library_items/useLibraryItems'
type NotebookContentProps = {
viewer: UserBasicData
@ -43,11 +43,10 @@ type NoteState = {
export function NotebookContent(props: NotebookContentProps): JSX.Element {
const isDark = isDarkTheme()
const { articleData, mutate } = useGetArticleQuery({
slug: props.item.slug,
username: props.viewer.profile.username,
includeFriendsHighlights: false,
})
const { data: article } = useGetLibraryItemContent(
props.viewer.profile.username as string,
props.item.slug as string
)
const [noteText, setNoteText] = useState<string>('')
const [showConfirmDeleteHighlightId, setShowConfirmDeleteHighlightId] =
useState<undefined | string>(undefined)
@ -112,7 +111,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
)
const highlights = useMemo(() => {
const result = articleData?.article.article.highlights
const result = article?.highlights
const note = result?.find((h) => h.type === 'NOTE')
if (note) {
noteState.current.note = note
@ -122,7 +121,7 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
setNoteText('')
}
return result
}, [articleData])
}, [article])
useEffect(() => {
if (highlights && props.onAnnotationsChanged) {
@ -179,16 +178,6 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
const [lastChanged, setLastChanged] = useState<Date | undefined>(undefined)
const [lastSaved, setLastSaved] = useState<Date | undefined>(undefined)
useEffect(() => {
const highlightsUpdated = () => {
mutate()
}
document.addEventListener('highlightsUpdated', highlightsUpdated)
return () => {
document.removeEventListener('highlightsUpdated', highlightsUpdated)
}
}, [mutate])
return (
<VStack
tabIndex={-1}
@ -256,9 +245,6 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
viewInReader={props.viewInReader}
setSetLabelsTarget={setLabelsTarget}
setShowConfirmDeleteHighlightId={setShowConfirmDeleteHighlightId}
updateHighlight={() => {
mutate()
}}
/>
))}
{sortedHighlights.length === 0 && (
@ -298,7 +284,6 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
props.item.id,
showConfirmDeleteHighlightId
)
mutate()
if (success) {
showSuccessToast('Highlight deleted.', {
position: 'bottom-right',
@ -333,7 +318,6 @@ export function NotebookContent(props: NotebookContentProps): JSX.Element {
console.log('update highlight: ', highlight)
}}
onOpenChange={() => {
mutate()
setLabelsTarget(undefined)
}}
/>

View File

@ -1,4 +1,4 @@
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } from '../../../lib/networking/library_items/useLibraryItems'
import { Box } from '../../elements/LayoutPrimitives'
import { v4 as uuidv4 } from 'uuid'
import { nanoid } from 'nanoid'
@ -36,8 +36,9 @@ export default function PdfArticleContainer(
const containerRef = useRef<HTMLDivElement | null>(null)
const [notebookKey, setNotebookKey] = useState<string>(uuidv4())
const [noteTarget, setNoteTarget] = useState<Highlight | undefined>(undefined)
const [noteTargetPageIndex, setNoteTargetPageIndex] =
useState<number | undefined>(undefined)
const [noteTargetPageIndex, setNoteTargetPageIndex] = useState<
number | undefined
>(undefined)
const highlightsRef = useRef<Highlight[]>([])
const annotationOmnivoreId = (annotation: Annotation): string | undefined => {

View File

@ -1,4 +1,4 @@
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } from '../../../lib/networking/library_items/useLibraryItems'
import { Button } from '../../elements/Button'
import { HStack } from '../../elements/LayoutPrimitives'
import { theme } from '../../tokens/stitches.config'

View File

@ -1,7 +1,7 @@
import dayjs, { Dayjs } from 'dayjs'
import { useCallback, useState } from 'react'
import { updatePageMutation } from '../../../lib/networking/mutations/updatePageMutation'
import { ArticleAttributes } from '../../../lib/networking/queries/useGetArticleQuery'
import { ArticleAttributes } 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'

View File

@ -18,7 +18,10 @@ import {
LibraryItemNode,
LibraryItems,
LibraryItemsQueryInput,
useArchiveItem,
useDeleteItem,
useGetLibraryItems,
useUpdateItemReadStatus,
} from '../../../lib/networking/library_items/useLibraryItems'
import {
useGetViewerQuery,
@ -110,6 +113,10 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element {
const [linkToEdit, setLinkToEdit] = useState<LibraryItem>()
const [linkToUnsubscribe, setLinkToUnsubscribe] = useState<LibraryItem>()
const archiveItem = useArchiveItem()
const deleteItem = useDeleteItem()
const updateItemReadStatus = useUpdateItemReadStatus()
const [queryInputs, setQueryInputs] =
useState<LibraryItemsQueryInput>(defaultQuery)
@ -121,19 +128,6 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element {
error: fetchItemsError,
} = useGetLibraryItems(props.folder, queryInputs)
// useEffect(() => {
// const handleRevalidate = () => {
// ;(async () => {
// console.log('revalidating library')
// await mutate()
// })()
// }
// document.addEventListener('revalidateLibrary', handleRevalidate)
// return () => {
// document.removeEventListener('revalidateLibrary', handleRevalidate)
// }
// }, [mutate])
useEffect(() => {
if (queryValue.startsWith('#')) {
debouncedFetchSearchResults(
@ -167,13 +161,6 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element {
window.localStorage.setItem('nav-return', router.asPath)
}, [router.asPath])
// const hasMore = useMemo(() => {
// if (!itemsPages) {
// return false
// }
// return itemsPages[itemsPages.length - 1].search.pageInfo.hasNextPage
// }, [itemsPages])
const libraryItems = useMemo(() => {
const items =
itemsPages?.pages
@ -387,64 +374,98 @@ export function LibraryContainer(props: LibraryContainerProps): JSX.Element {
return
}
// switch (action) {
// case 'showDetail':
// const username = viewerData?.me?.profile.username
// if (username) {
// setActiveCardId(item.node.id)
// if (item.node.state === State.PROCESSING) {
// router.push(`/article?url=${encodeURIComponent(item.node.url)}`)
// } else {
// const dl =
// item.node.pageType === PageType.HIGHLIGHTS
// ? `#${item.node.id}`
// : ''
// router.push(`/${username}/${item.node.slug}` + dl)
// }
// }
// break
// case 'showOriginal':
// const url = item.node.originalArticleUrl
// if (url) {
// window.open(url, '_blank')
// }
// break
// case 'archive':
// performActionOnItem('archive', item)
// break
// case 'unarchive':
// performActionOnItem('unarchive', item)
// break
// case 'delete':
// performActionOnItem('delete', item)
// break
// case 'restore':
// performActionOnItem('restore', item)
// break
// case 'mark-read':
// performActionOnItem('mark-read', item)
// break
// case 'mark-unread':
// performActionOnItem('mark-unread', item)
// break
// case 'set-labels':
// setLabelsTarget(item)
// break
// case 'open-notebook':
// if (!notebookTarget) {
// setNotebookTarget(item)
// } else {
// setNotebookTarget(undefined)
// }
// break
// case 'unsubscribe':
// performActionOnItem('unsubscribe', item)
// case 'update-item':
// performActionOnItem('update-item', item)
// break
// default:
// console.warn('unknown action: ', action)
// }
switch (action) {
case 'showDetail':
const username = viewerData?.me?.profile.username
if (username) {
setActiveCardId(item.node.id)
if (item.node.state === State.PROCESSING) {
router.push(`/article?url=${encodeURIComponent(item.node.url)}`)
} else {
router.push(`/${username}/${item.node.slug}`)
}
}
break
case 'showOriginal':
const url = item.node.originalArticleUrl
if (url) {
window.open(url, '_blank')
}
break
case 'archive':
case 'unarchive':
try {
await archiveItem.mutateAsync({
linkId: item.node.id,
archived: action == 'archive',
})
} catch {
showErrorToast(`Error ${action}ing item`, {
position: 'bottom-right',
})
return
}
showSuccessToast(`Item ${action}d`, {
position: 'bottom-right',
})
break
case 'delete':
try {
await deleteItem.mutateAsync(item.node.id)
} catch {
showErrorToast(`Error deleting item`, {
position: 'bottom-right',
})
return
}
showSuccessToast(`Item deleted`, {
position: 'bottom-right',
})
break
case 'mark-read':
case 'mark-unread':
const desc = action == 'mark-read' ? 'read' : 'unread'
const values =
action == 'mark-read'
? {
readingProgressPercent: 100,
readingProgressTopPercent: 100,
readingProgressAnchorIndex: 0,
}
: {
readingProgressPercent: 0,
readingProgressTopPercent: 0,
readingProgressAnchorIndex: 0,
}
try {
await updateItemReadStatus.mutateAsync({
id: item.node.id,
force: true,
...values,
})
} catch {
showErrorToast(`Error marking as ${desc}`, {
position: 'bottom-right',
})
return
}
break
case 'set-labels':
setLabelsTarget(item)
break
case 'open-notebook':
if (!notebookTarget) {
setNotebookTarget(item)
} else {
setNotebookTarget(undefined)
}
break
case 'unsubscribe':
setLinkToUnsubscribe(item.node)
break
default:
console.warn('unknown action: ', action)
}
}
const modalTargetItem = useMemo(() => {
@ -1187,9 +1208,6 @@ export function LibraryItemsLayout(
</VStack>
{props.showEditTitleModal && (
<EditLibraryItemModal
updateItem={(item: LibraryItem) =>
props.actionHandler('update-item', item)
}
onOpenChange={() => {
props.setShowEditTitleModal(false)
props.setLinkToEdit(undefined)