Added resize functionality to notebooks of Article and PDF

This commit is contained in:
nyatinte
2024-04-23 18:10:29 +09:00
parent b6e3321d04
commit 3c765c9a4d
4 changed files with 144 additions and 146 deletions

View File

@ -26,13 +26,12 @@ import { isTouchScreenDevice } from '../../../lib/deviceType'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { SetHighlightLabelsModalPresenter } from './SetLabelsModalPresenter'
import SlidingPane from 'react-sliding-pane'
import 'react-sliding-pane/dist/react-sliding-pane.css'
import { NotebookContent } from './Notebook'
import { NotebookHeader } from './NotebookHeader'
import useGetWindowDimensions from '../../../lib/hooks/useGetWindowDimensions'
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
import { Resizable } from 're-resizable'
import { ResizableSidebar } from './ResizableSidebar'
type HighlightsLayerProps = {
viewer: UserBasicData
@ -81,15 +80,13 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
const focusedHighlightMousePos = useRef({ pageX: 0, pageY: 0 })
const [currentHighlightIdx, setCurrentHighlightIdx] = useState(0)
const [focusedHighlight, setFocusedHighlight] = useState<
Highlight | undefined
>(undefined)
const [focusedHighlight, setFocusedHighlight] =
useState<Highlight | undefined>(undefined)
const [selectionData, setSelectionData] = useSelection(highlightLocations)
const [labelsTarget, setLabelsTarget] = useState<Highlight | undefined>(
undefined
)
const [labelsTarget, setLabelsTarget] =
useState<Highlight | undefined>(undefined)
const [
confirmDeleteHighlightWithNoteId,
@ -577,7 +574,6 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
selectionData,
setSelectionData,
updateHighlightColor,
confirmDeleteHighlightWithNoteId,
]
)
@ -848,72 +844,41 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
/>
</>
)}
<SlidingPane
className="sliding-pane-class"
isOpen={props.showHighlightsModal}
width="fit-content"
hideHeader={true}
from="right"
overlayClassName="slide-panel-overlay"
onRequestClose={() => {
<ResizableSidebar
isShow={props.showHighlightsModal}
onClose={() => {
props.setShowHighlightsModal(false)
}}
>
<Resizable
onResize={(_e, _direction, ref) => {
if (parseInt(ref.style.width) < 210) {
props.setShowHighlightsModal(false)
}
}}
defaultSize={{
width: windowDimensions.width < 600 ? '100%' : '420px',
height: '100%',
}}
enable={
windowDimensions.width < 600
? false
: {
top: false,
right: false,
bottom: false,
left: true,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}
}
>
<NotebookHeader
viewer={props.viewer}
item={props.item}
setShowNotebook={props.setShowHighlightsModal}
/>
<NotebookContent
viewer={props.viewer}
item={props.item}
// highlights={highlights}
// onClose={handleCloseNotebook}
viewInReader={(highlightId) => {
// The timeout here is a bit of a hack to work around rerendering
setTimeout(() => {
const target = document.querySelector(
`[omnivore-highlight-id="${highlightId}"]`
)
target?.scrollIntoView({
block: 'center',
behavior: 'auto',
})
}, 1)
history.replaceState(
undefined,
window.location.href,
`#${highlightId}`
<NotebookHeader
viewer={props.viewer}
item={props.item}
setShowNotebook={props.setShowHighlightsModal}
/>
<NotebookContent
viewer={props.viewer}
item={props.item}
// highlights={highlights}
// onClose={handleCloseNotebook}
viewInReader={(highlightId) => {
// The timeout here is a bit of a hack to work around rerendering
setTimeout(() => {
const target = document.querySelector(
`[omnivore-highlight-id="${highlightId}"]`
)
}}
/>
</Resizable>
</SlidingPane>
target?.scrollIntoView({
block: 'center',
behavior: 'auto',
})
}, 1)
history.replaceState(
undefined,
window.location.href,
`#${highlightId}`
)
}}
/>
</ResizableSidebar>
</>
)
}

View File

@ -1,12 +1,11 @@
import { ReadableItem } from '../../../lib/networking/queries/useGetLibraryItemsQuery'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import SlidingPane from 'react-sliding-pane'
import 'react-sliding-pane/dist/react-sliding-pane.css'
import { NotebookContent } from './Notebook'
import { NotebookHeader } from './NotebookHeader'
import useGetWindowDimensions from '../../../lib/hooks/useGetWindowDimensions'
import { useRouter } from 'next/router'
import { showErrorToast } from '../../../lib/toastHelpers'
import { ResizableSidebar } from './ResizableSidebar'
type NotebookPresenterProps = {
viewer: UserBasicData
@ -18,52 +17,39 @@ type NotebookPresenterProps = {
}
export const NotebookPresenter = (props: NotebookPresenterProps) => {
const windowDimensions = useGetWindowDimensions()
const router = useRouter()
return (
<SlidingPane
className="sliding-pane-class"
isOpen={props.open}
width={windowDimensions.width < 600 ? '100%' : '420px'}
hideHeader={true}
from="right"
overlayClassName="slide-panel-overlay"
onRequestClose={() => {
props.setOpen(false)
}}
>
<>
<NotebookHeader
viewer={props.viewer}
item={props.item}
setShowNotebook={props.setOpen}
/>
<NotebookContent
viewer={props.viewer}
item={props.item}
viewInReader={(highlightId) => {
if (!router || !router.isReady || !props.viewer) {
showErrorToast('Error navigating to highlight')
return
}
router.push(
{
pathname: '/[username]/[slug]',
query: {
username: props.viewer.profile.username,
slug: props.item.slug,
},
hash: highlightId,
<ResizableSidebar isShow={props.open} onClose={() => props.setOpen(false)}>
<NotebookHeader
viewer={props.viewer}
item={props.item}
setShowNotebook={props.setOpen}
/>
<NotebookContent
viewer={props.viewer}
item={props.item}
viewInReader={(highlightId) => {
if (!router || !router.isReady || !props.viewer) {
showErrorToast('Error navigating to highlight')
return
}
router.push(
{
pathname: '/[username]/[slug]',
query: {
username: props.viewer.profile.username,
slug: props.item.slug,
},
`/${props.viewer.profile.username}/${props.item.slug}#${highlightId}`,
{
scroll: false,
}
)
}}
/>
</>
</SlidingPane>
hash: highlightId,
},
`/${props.viewer.profile.username}/${props.item.slug}#${highlightId}`,
{
scroll: false,
}
)
}}
/>
</ResizableSidebar>
)
}

View File

@ -16,11 +16,11 @@ import { HighlightNoteModal } from './HighlightNoteModal'
import { showErrorToast } from '../../../lib/toastHelpers'
import { DEFAULT_HEADER_HEIGHT } from '../homeFeed/HeaderSpacer'
import { UserBasicData } from '../../../lib/networking/queries/useGetViewerQuery'
import SlidingPane from 'react-sliding-pane'
import 'react-sliding-pane/dist/react-sliding-pane.css'
import { NotebookContent } from './Notebook'
import { NotebookHeader } from './NotebookHeader'
import useWindowDimensions from '../../../lib/hooks/useGetWindowDimensions'
import { ResizableSidebar } from './ResizableSidebar'
export type PdfArticleContainerProps = {
viewer: UserBasicData
@ -35,9 +35,8 @@ 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 => {
@ -595,35 +594,28 @@ export default function PdfArticleContainer(
}}
/>
)}
<SlidingPane
className="sliding-pane-class"
isOpen={props.showHighlightsModal}
width={windowDimensions.width < 600 ? '100%' : '420px'}
hideHeader={true}
from="right"
overlayClassName="slide-panel-overlay"
onRequestClose={() => {
<ResizableSidebar
isShow={props.showHighlightsModal}
onClose={() => {
props.setShowHighlightsModal(false)
}}
>
<>
<NotebookHeader
viewer={props.viewer}
item={props.article}
setShowNotebook={props.setShowHighlightsModal}
/>
<NotebookContent
viewer={props.viewer}
item={props.article}
viewInReader={(highlightId) => {
const event = new CustomEvent('scrollToHighlightId', {
detail: highlightId,
})
document.dispatchEvent(event)
}}
/>
</>
</SlidingPane>
<NotebookHeader
viewer={props.viewer}
item={props.article}
setShowNotebook={props.setShowHighlightsModal}
/>
<NotebookContent
viewer={props.viewer}
item={props.article}
viewInReader={(highlightId) => {
const event = new CustomEvent('scrollToHighlightId', {
detail: highlightId,
})
document.dispatchEvent(event)
}}
/>
</ResizableSidebar>
</Box>
)
}

View File

@ -0,0 +1,55 @@
import SlidingPane from 'react-sliding-pane'
import { Resizable, ResizeCallback } from 're-resizable'
import useGetWindowDimensions from '../../../lib/hooks/useGetWindowDimensions'
type ResizableSidebarProps = {
isShow: boolean
onClose: () => void
children: React.ReactNode
}
export function ResizableSidebar(props: ResizableSidebarProps): JSX.Element {
const windowDimensions = useGetWindowDimensions()
const handleResize: ResizeCallback = (_e, _direction, ref) => {
if (parseInt(ref.style.width) < 210) {
props.onClose()
}
}
return (
<SlidingPane
className="sliding-pane-class"
isOpen={props.isShow}
width="fit-content"
hideHeader={true}
from="right"
overlayClassName="slide-panel-overlay"
onRequestClose={props.onClose}
>
<Resizable
onResize={handleResize}
defaultSize={{
width: windowDimensions.width < 600 ? '100%' : '420px',
height: '100%',
}}
enable={
windowDimensions.width < 600
? false
: {
top: false,
right: false,
bottom: false,
left: true,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
}
}
>
{props.children}
</Resizable>
</SlidingPane>
)
}