diff --git a/static/js/app.js b/static/js/app.js index 1449eb8..0e98720 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -2111,6 +2111,28 @@ document.addEventListener('keydown', e => { if (e.key === 'ArrowRight') { e.preventDefault(); pdfGoToPage(pdfCurrentPage + 1); } if (e.key === 'ArrowLeft') { e.preventDefault(); pdfGoToPage(pdfCurrentPage - 1); } } + + // Vim-style scroll — ignore when typing in an input + const tag = document.activeElement?.tagName; + if (tag !== 'INPUT' && tag !== 'TEXTAREA') { + const contentEl = $('reader-content'); + if (contentEl) { + const small = Math.round(contentEl.clientHeight * 0.08); + const large = Math.round(contentEl.clientHeight * 0.85); + if (e.key === 'j') { e.preventDefault(); contentEl.scrollBy({top: small, behavior: 'smooth'}); } + if (e.key === 'k') { e.preventDefault(); contentEl.scrollBy({top: -small, behavior: 'smooth'}); } + if (e.key === 'd') { e.preventDefault(); contentEl.scrollBy({top: large / 2, behavior: 'smooth'}); } + if (e.key === 'u') { e.preventDefault(); contentEl.scrollBy({top: -large / 2, behavior: 'smooth'}); } + if (e.key === 'f') { e.preventDefault(); contentEl.scrollBy({top: large, behavior: 'smooth'}); } + if (e.key === 'b') { e.preventDefault(); contentEl.scrollBy({top: -large, behavior: 'smooth'}); } + if (e.key === 'g') { e.preventDefault(); contentEl.scrollTop = 0; } + if (e.key === 'G') { e.preventDefault(); contentEl.scrollTop = contentEl.scrollHeight; } + if (currentPdfDoc && !readerSettings.pdfPaginated) { + if (e.key === 'n') { e.preventDefault(); pdfGoToPage(pdfCurrentPage + 1); } + if (e.key === 'p') { e.preventDefault(); pdfGoToPage(pdfCurrentPage - 1); } + } + } + } } });