From 1fb3c44b9311004c1c6de9962363c07cce5fd3c4 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Thu, 23 Mar 2023 11:22:51 +0800 Subject: [PATCH] WIP: Use a reducer when creating notes --- .../templates/article/NotebookModal.tsx | 115 +++++++++++++----- 1 file changed, 84 insertions(+), 31 deletions(-) diff --git a/packages/web/components/templates/article/NotebookModal.tsx b/packages/web/components/templates/article/NotebookModal.tsx index b825235f2..96d15f338 100644 --- a/packages/web/components/templates/article/NotebookModal.tsx +++ b/packages/web/components/templates/article/NotebookModal.tsx @@ -12,9 +12,11 @@ import type { Highlight } from '../../../lib/networking/fragments/highlightFragm import { HighlightView } from '../../patterns/HighlightView' import { ChangeEvent, + Dispatch, useCallback, useEffect, useMemo, + useReducer, useRef, useState, } from 'react' @@ -39,6 +41,7 @@ import { v4 as uuidv4 } from 'uuid' import { nanoid } from 'nanoid' import throttle from 'lodash/throttle' import { deleteHighlightMutation } from '../../../lib/networking/mutations/deleteHighlightMutation' +import { LibraryItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery' const mdParser = new MarkdownIt() @@ -51,6 +54,15 @@ type NotebookModalProps = { onOpenChange: (open: boolean) => void } +type HighlightListReducerAction = { + type: string + itemId?: string + createId?: string + removeId?: string + highlight?: Highlight + highlights?: Highlight[] +} + export const getHighlightLocation = (patch: string): number | undefined => { const dmp = new diff_match_patch() const patches = dmp.patch_fromText(patch) @@ -68,21 +80,60 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { const [notesEditMode, setNotesEditMode] = useState(true) const [, updateState] = useState({}) + const listReducer = ( + state: Highlight[], + action: HighlightListReducerAction + ) => { + switch (action.type) { + case 'RESET': + return action.highlights ?? [] + case 'CREATE_NOTE': + if (!action.highlight) { + throw new Error('Unable to create note') + } + return [...(action.highlights ?? []), action.highlight] + case 'UPDATE_NOTE': + return action.highlights ?? [] + case 'REMOVE_HIGHLIGHT': + // const item = state.find((li) => li.node.id === action.itemId) + // if (item && item.node.highlights) { + // item.node.highlights = item.node.highlights.filter( + // (h) => h.id !== action.highlightId + // ) + // } + // const result = state.filter( + // (item) => item.node.highlights && item.node.highlights.length > 0 + // ) + // return result + default: + throw new Error() + } + } + + const [highlights, dispatchList] = useReducer(listReducer, []) + + useEffect(() => { + dispatchList({ + type: 'RESET', + highlights: props.highlights, + }) + }, [props.highlights]) + const exportHighlights = useCallback(() => { ;(async () => { - if (!props.highlights) { + if (!highlights) { showErrorToast('No highlights to export') return } - const markdown = highlightsAsMarkdown(props.highlights) + const markdown = highlightsAsMarkdown(highlights) await navigator.clipboard.writeText(markdown) showSuccessToast('Highlight copied') })() - }, [props.highlights]) + }, [highlights]) const deleteDocumentNote = useCallback(() => { ;(async () => { - const notes = props.highlights.filter((h) => h.type == 'NOTE') + const notes = highlights.filter((h) => h.type == 'NOTE') notes.forEach(async (n) => { try { @@ -110,7 +161,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { return 0 } - return props.highlights + return highlights .filter((h) => h.type === undefined || h.type === 'HIGHLIGHT') .sort((a: Highlight, b: Highlight) => { if (a.highlightPositionPercent && b.highlightPositionPercent) { @@ -127,7 +178,7 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { } catch {} return a.createdAt.localeCompare(b.createdAt) }) - }, [props.highlights]) + }, [highlights]) return ( @@ -188,13 +239,14 @@ export function NotebookModal(props: NotebookModalProps): JSX.Element { /> h.type == 'NOTE')} + highlight={highlights.find((h) => h.type == 'NOTE')} sizeMode={sizeMode} mode={notesEditMode ? 'edit' : 'read'} setEditMode={setNotesEditMode} + dispatchList={dispatchList} /> - {/* {props.highlights.map((highlight) => ( + {props.highlights.map((highlight) => ( {highlight.annotation}