Merge pull request #2928 from omnivore-app/feat/web-next-prev-navigation

Allow navigating to next/previous items on the web with keyboard
This commit is contained in:
Jackson Harper
2023-10-13 18:24:33 +08:00
committed by GitHub
3 changed files with 66 additions and 7 deletions

View File

@ -180,7 +180,7 @@ export function ArticleActionsMenu(
</Button>
) : (
<Button
title="Unarchive (u)"
title="Unarchive (e)"
style="articleActionIcon"
onClick={() => props.articleActionHandler('unarchive')}
>

View File

@ -191,6 +191,15 @@ export function HomeFeedContainer(): JSX.Element {
return items
}, [itemsPages, performActionOnItem])
useEffect(() => {
if (localStorage) {
localStorage.setItem(
'library-slug-list',
JSON.stringify(libraryItems.map((li) => li.node.slug))
)
}
}, [libraryItems])
useEffect(() => {
const timeout: NodeJS.Timeout[] = []

View File

@ -78,6 +78,34 @@ export default function Home(): JSX.Element {
})
}, [articleData?.article.article])
const goNextOrHome = useCallback(() => {
const listStr = localStorage.getItem('library-slug-list')
if (article && listStr && viewerData?.me) {
const libraryList = JSON.parse(listStr) as string[]
const idx = libraryList.findIndex((slug) => slug == article.slug)
if (idx != -1 && idx < libraryList.length - 1) {
const nextSlug = libraryList[idx + 1] as string
router.push(`/${viewerData?.me.profile.username}/${nextSlug}`)
return
}
}
router.push(`/home`)
}, [router, viewerData, article])
const goPreviousOrHome = useCallback(() => {
const listStr = localStorage.getItem('library-slug-list')
if (article && listStr && viewerData?.me) {
const libraryList = JSON.parse(listStr) as string[]
const idx = libraryList.findIndex((slug) => slug == article.slug)
if (idx > 0) {
const previousSlug = libraryList[idx - 1] as string
router.push(`/${viewerData?.me.profile.username}/${previousSlug}`)
return
}
}
router.push(`/home`)
}, [router, viewerData, article])
const actionHandler = useCallback(
async (action: string, arg?: unknown) => {
switch (action) {
@ -99,8 +127,7 @@ export default function Home(): JSX.Element {
})
}
})
router.push(`/home`)
goNextOrHome()
}
break
case 'archive':
@ -116,7 +143,7 @@ export default function Home(): JSX.Element {
position: 'bottom-right',
})
} else {
router.push(`/home`)
goNextOrHome()
showSuccessToast('Page archived', {
position: 'bottom-right',
})
@ -138,7 +165,7 @@ export default function Home(): JSX.Element {
position: 'bottom-right',
})
} else {
router.push(`/home`)
goNextOrHome()
}
})
}
@ -169,7 +196,7 @@ export default function Home(): JSX.Element {
break
}
},
[article, cache, mutate, router, readerSettings]
[article, viewerData, cache, mutate, router, readerSettings]
)
useEffect(() => {
@ -197,14 +224,19 @@ export default function Home(): JSX.Element {
document.addEventListener('openOriginalArticle', openOriginalArticle)
document.addEventListener('showEditModal', showEditModal)
document.addEventListener('goNextOrHome', goNextOrHome)
document.addEventListener('goPreviousOrHome', goPreviousOrHome)
return () => {
document.removeEventListener('archive', archive)
document.removeEventListener('mark-read', markRead)
document.removeEventListener('delete', deletePage)
document.removeEventListener('openOriginalArticle', openOriginalArticle)
document.removeEventListener('showEditModal', showEditModal)
document.removeEventListener('goNextOrHome', goNextOrHome)
document.removeEventListener('goPreviousOrHome', goPreviousOrHome)
}
}, [actionHandler])
}, [actionHandler, goNextOrHome, goPreviousOrHome])
useEffect(() => {
if (article && viewerData?.me) {
@ -386,6 +418,24 @@ export default function Home(): JSX.Element {
shortcut: ['i'],
perform: () => setShowEditModal(true),
},
{
id: 'go_previous',
section: 'Article',
name: 'Go to Previous',
shortcut: ['g', 'p'],
perform: () => {
document.dispatchEvent(new Event('goPreviousOrHome'))
},
},
{
id: 'go_next',
section: 'Article',
name: 'Go to Next',
shortcut: ['g', 'n'],
perform: () => {
document.dispatchEvent(new Event('goNextOrHome'))
},
},
],
[readerSettings, showHighlightsModal]
)