|
1 | 1 | <script lang="ts"> |
2 | | - import { getContext, onDestroy, tick } from 'svelte'; |
3 | | - import panzoom, { type PanZoom } from 'panzoom'; |
| 2 | + import { getContext, tick } from 'svelte'; |
4 | 3 | import { marked } from 'marked'; |
5 | 4 | import DOMPurify from 'dompurify'; |
6 | 5 | import { settings } from '$lib/stores'; |
7 | 6 | import { isCodeFile } from '$lib/utils/codeHighlight'; |
8 | 7 | import { initMermaid, renderMermaidDiagram } from '$lib/utils'; |
9 | 8 | import Spinner from '../../common/Spinner.svelte'; |
10 | 9 | import PDFViewer from '../../common/PDFViewer.svelte'; |
| 10 | + import PanzoomContainer from '../../common/PanzoomContainer.svelte'; |
11 | 11 | import JsonTreeView from './JsonTreeView.svelte'; |
12 | 12 | import NotebookView from './NotebookView.svelte'; |
13 | 13 | import SqliteView from './SqliteView.svelte'; |
|
250 | 250 | showRaw = true; |
251 | 251 | } |
252 | 252 |
|
253 | | - let pzInstance: PanZoom | null = null; |
254 | | -
|
255 | | - const initImagePanzoom = (node: HTMLElement) => { |
256 | | - pzInstance = panzoom(node, { |
257 | | - bounds: true, |
258 | | - boundsPadding: 0.1, |
259 | | - zoomSpeed: 0.065, |
260 | | - zoomDoubleClickSpeed: 1 |
261 | | - }); |
262 | | - }; |
263 | | -
|
| 253 | + let panzoomRef: PanzoomContainer; |
264 | 254 | export const resetImageView = () => { |
265 | | - if (pzInstance) { |
266 | | - pzInstance.moveTo(0, 0); |
267 | | - pzInstance.zoomAbs(0, 0, 1); |
268 | | - } |
269 | | - }; |
270 | | -
|
271 | | - export const disposePanzoom = () => { |
272 | | - if (pzInstance) { |
273 | | - pzInstance.dispose(); |
274 | | - pzInstance = null; |
275 | | - } |
| 255 | + panzoomRef?.reset(); |
276 | 256 | }; |
277 | 257 |
|
278 | 258 | export const resetPdfView = () => { |
279 | 259 | pdfViewerRef?.resetView(); |
280 | 260 | }; |
281 | | -
|
282 | | - onDestroy(() => { |
283 | | - disposePanzoom(); |
284 | | - }); |
285 | 261 | </script> |
286 | 262 |
|
287 | 263 | <div |
|
293 | 269 | {#if fileLoading} |
294 | 270 | <div class="flex items-center justify-center h-full"><Spinner className="size-4" /></div> |
295 | 271 | {:else if fileImageUrl !== null} |
296 | | - <div class="w-full h-full flex items-center justify-center" use:initImagePanzoom> |
| 272 | + <PanzoomContainer |
| 273 | + bind:this={panzoomRef} |
| 274 | + className="w-full h-full flex items-center justify-center" |
| 275 | + options={{ zoomDoubleClickSpeed: 1 }} |
| 276 | + > |
297 | 277 | <img |
298 | 278 | src={fileImageUrl} |
299 | 279 | alt={selectedFile?.split('/').pop()} |
300 | 280 | class="max-w-full max-h-full object-contain p-3" |
301 | 281 | draggable="false" |
302 | 282 | /> |
303 | | - </div> |
| 283 | + </PanzoomContainer> |
304 | 284 | {:else if fileVideoUrl !== null} |
305 | 285 | <div class="w-full h-full flex items-center justify-center bg-black"> |
306 | 286 | <!-- svelte-ignore a11y-media-has-caption --> |
|
343 | 323 | </div> |
344 | 324 | {:else if fileOfficeSlides !== null && fileOfficeSlides.length > 0} |
345 | 325 | <div class="flex flex-col h-full"> |
346 | | - <div |
347 | | - class="w-full flex-1 min-h-0 flex items-center justify-center overflow-hidden" |
348 | | - use:initImagePanzoom |
| 326 | + <PanzoomContainer |
| 327 | + bind:this={panzoomRef} |
| 328 | + className="w-full flex-1 min-h-0 flex items-center justify-center overflow-hidden" |
| 329 | + options={{ zoomDoubleClickSpeed: 1 }} |
349 | 330 | > |
350 | 331 | <img |
351 | 332 | src={fileOfficeSlides[currentSlide]} |
352 | 333 | alt="Slide {currentSlide + 1}" |
353 | 334 | class="max-w-full max-h-full object-contain p-3" |
354 | 335 | draggable="false" |
355 | 336 | /> |
356 | | - </div> |
| 337 | + </PanzoomContainer> |
357 | 338 | {#if fileOfficeSlides.length > 1} |
358 | 339 | <div |
359 | 340 | class="flex items-center justify-center gap-3 py-2 px-3 border-t border-gray-100 dark:border-gray-800 text-xs text-gray-500" |
|
0 commit comments