Skip to content

Commit

Permalink
Merge pull request #3852 from nyatinte/feat/resizable-notebook
Browse files Browse the repository at this point in the history
Added resize functionality to notebooks of Article and PDF
  • Loading branch information
jacksonh committed Apr 23, 2024
2 parents fc80d1c + 3c765c9 commit 6db838c
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 146 deletions.
107 changes: 36 additions & 71 deletions packages/web/components/templates/article/HighlightsLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -577,7 +574,6 @@ export function HighlightsLayer(props: HighlightsLayerProps): JSX.Element {
selectionData,
setSelectionData,
updateHighlightColor,
confirmDeleteHighlightWithNoteId,
]
)

Expand Down Expand Up @@ -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>
</>
)
}
76 changes: 31 additions & 45 deletions packages/web/components/templates/article/NotebookPresenter.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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>
)
}
52 changes: 22 additions & 30 deletions packages/web/components/templates/article/PdfArticleContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 => {
Expand Down Expand Up @@ -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>
)
}
55 changes: 55 additions & 0 deletions packages/web/components/templates/article/ResizableSidebar.tsx
Original file line number Diff line number Diff line change
@@ -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>
)
}

0 comments on commit 6db838c

Please sign in to comment.