kopia lustrzana https://github.com/elk-zone/elk
fix: disable j/k keyboard shortcut when enabled virtual scroller
rodzic
9d327f17aa
commit
06f8bb8388
|
@ -7,6 +7,7 @@ export default defineNuxtPlugin(({ $scrollToTop }) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const i18n = useNuxtApp().$i18n
|
const i18n = useNuxtApp().$i18n
|
||||||
const { y } = useWindowScroll({ behavior: 'instant' })
|
const { y } = useWindowScroll({ behavior: 'instant' })
|
||||||
|
const virtualScroller = usePreferences('experimentalVirtualScroller')
|
||||||
|
|
||||||
// disable shortcuts when focused on inputs (https://vueuse.org/core/usemagickeys/#conditionally-disable)
|
// disable shortcuts when focused on inputs (https://vueuse.org/core/usemagickeys/#conditionally-disable)
|
||||||
const activeElement = useActiveElement()
|
const activeElement = useActiveElement()
|
||||||
|
@ -78,48 +79,53 @@ export default defineNuxtPlugin(({ $scrollToTop }) => {
|
||||||
}
|
}
|
||||||
whenever(logicAnd(isAuthenticated, notUsingInput, keys['.']), showNewItems)
|
whenever(logicAnd(isAuthenticated, notUsingInput, keys['.']), showNewItems)
|
||||||
|
|
||||||
const statusSelector = '[aria-roledescription="status-card"]'
|
// TODO: virtual scroller cannot load off-screen post
|
||||||
|
// that prevents focusing next post properly
|
||||||
|
// we disabled this shortcut when enabled virtual scroller
|
||||||
|
if (!virtualScroller.value) {
|
||||||
|
const statusSelector = '[aria-roledescription="status-card"]'
|
||||||
|
|
||||||
// find the nearest status element id traversing up from the current active element
|
// find the nearest status element id traversing up from the current active element
|
||||||
// `activeElement` can be some of an element within a status element
|
// `activeElement` can be some of an element within a status element
|
||||||
// otherwise, reach to the root `<html>`
|
// otherwise, reach to the root `<html>`
|
||||||
function getActiveStatueId(element: HTMLElement): string | undefined {
|
function getActiveStatueId(element: HTMLElement): string | undefined {
|
||||||
if (element.nodeName === 'HTML')
|
if (element.nodeName === 'HTML')
|
||||||
return undefined
|
return undefined
|
||||||
|
|
||||||
if (element.matches(statusSelector))
|
if (element.matches(statusSelector))
|
||||||
return element.id
|
return element.id
|
||||||
|
|
||||||
return getActiveStatueId(element.parentNode as HTMLElement)
|
return getActiveStatueId(element.parentNode as HTMLElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusNextOrPreviousStatus(direction: 'next' | 'previous') {
|
function focusNextOrPreviousStatus(direction: 'next' | 'previous') {
|
||||||
const activeStatusId = activeElement.value ? getActiveStatueId(activeElement.value) : undefined
|
const activeStatusId = activeElement.value ? getActiveStatueId(activeElement.value) : undefined
|
||||||
const nextOrPreviousStatusId = getNextOrPreviousStatusId(activeStatusId, direction)
|
const nextOrPreviousStatusId = getNextOrPreviousStatusId(activeStatusId, direction)
|
||||||
if (nextOrPreviousStatusId) {
|
if (nextOrPreviousStatusId) {
|
||||||
const status = document.getElementById(nextOrPreviousStatusId)
|
const status = document.getElementById(nextOrPreviousStatusId)
|
||||||
if (status) {
|
if (status) {
|
||||||
status.focus({ preventScroll: true })
|
status.focus({ preventScroll: true })
|
||||||
const topBarHeight = 58
|
const topBarHeight = 58
|
||||||
y.value += status.getBoundingClientRect().top - topBarHeight
|
y.value += status.getBoundingClientRect().top - topBarHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function getNextOrPreviousStatusId(currentStatusId: string | undefined, direction: 'next' | 'previous'): string | undefined {
|
function getNextOrPreviousStatusId(currentStatusId: string | undefined, direction: 'next' | 'previous'): string | undefined {
|
||||||
const statusIds = [...document.querySelectorAll(statusSelector)].map(s => s.id)
|
const statusIds = [...document.querySelectorAll(statusSelector)].map(s => s.id)
|
||||||
if (currentStatusId === undefined) {
|
if (currentStatusId === undefined) {
|
||||||
// if there is no selection, always focus on the first status
|
// if there is no selection, always focus on the first status
|
||||||
return statusIds[0]
|
return statusIds[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentIndex = statusIds.findIndex(id => id === currentStatusId)
|
||||||
|
const statusId = direction === 'next'
|
||||||
|
? statusIds[Math.min(currentIndex + 1, statusIds.length)]
|
||||||
|
: statusIds[Math.max(0, currentIndex - 1)]
|
||||||
|
return statusId
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentIndex = statusIds.findIndex(id => id === currentStatusId)
|
whenever(logicAnd(notUsingInput, keys.j), () => focusNextOrPreviousStatus('next'))
|
||||||
const statusId = direction === 'next'
|
whenever(logicAnd(notUsingInput, keys.k), () => focusNextOrPreviousStatus('previous'))
|
||||||
? statusIds[Math.min(currentIndex + 1, statusIds.length)]
|
|
||||||
: statusIds[Math.max(0, currentIndex - 1)]
|
|
||||||
return statusId
|
|
||||||
}
|
}
|
||||||
|
|
||||||
whenever(logicAnd(notUsingInput, keys.j), () => focusNextOrPreviousStatus('next'))
|
|
||||||
whenever(logicAnd(notUsingInput, keys.k), () => focusNextOrPreviousStatus('previous'))
|
|
||||||
})
|
})
|
||||||
|
|
Ładowanie…
Reference in New Issue