Added resize functionality to notebooks of Article and PDF
This commit is contained in:
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user