feat(renderer): PDF viewer with page nav & zoom controls (M10.2)

- PdfViewer.vue: lazy-loads pdfjs-dist, renders to canvas
- Page navigation (arrows), zoom controls (50%–200%)
- Keyboard navigation (arrow keys)
- Integrated into content panel via openPdfViewer()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-03 23:50:07 +00:00
co-authored by Claude Opus 4.6
parent edb4bbadcd
commit 7a3d874f5e
5 changed files with 334 additions and 1 deletions
@@ -93,6 +93,12 @@
:title="longFormArticle.title"
@back="closeLongFormArticle"
/>
<PdfViewer
v-else-if="pdfUrl"
:url="pdfUrl.url"
:title="pdfUrl.title"
@back="closePdfViewer"
/>
<!-- Grid views by active tab -->
<component
@@ -177,6 +183,7 @@ import PodcastDetail from './PodcastDetail.vue'
import NewsGrid from './NewsGrid.vue'
import ArticleDetail from './ArticleDetail.vue'
import ArticleReader from '@/components/renderers/ArticleReader.vue'
import PdfViewer from '@/components/renderers/PdfViewer.vue'
import MagazineGrid from './MagazineGrid.vue'
import ProjectGrid from './ProjectGrid.vue'
import NostrGrid from './NostrGrid.vue'
@@ -227,11 +234,13 @@ const {
closeArticleDetail,
longFormArticle,
closeLongFormArticle,
pdfUrl,
closePdfViewer,
closePanel,
} = useContentPanel()
const hasDetailOpen = computed(() =>
!!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value || selectedDesignSystemItem.value || longFormArticle.value)
!!(selectedFilm.value || selectedBook.value || selectedTVSeries.value || selectedSong.value || selectedPodcast.value || selectedArticle.value || selectedDesignSystemItem.value || longFormArticle.value || pdfUrl.value)
)
const windowWidth = ref(window.innerWidth)