triiiceratops 0.16.6 → 0.16.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -173,6 +173,17 @@
173
173
 
174
174
  OSD = osdModule.default || osdModule;
175
175
  patchIiifLevel0ProfileCompatibility(OSD);
176
+ const userAgent = navigator.userAgent || '';
177
+ const isAndroidChrome =
178
+ /Android/i.test(userAgent) && /\bChrome\//i.test(userAgent);
179
+ const consumerOverrides = viewerState.config?.openSeadragonConfig ?? {};
180
+
181
+ // Prefer canvas first on Android Chrome unless consumer overrides drawer.
182
+ // This avoids known WebGL tile rendering issues on some mobile devices.
183
+ const defaultDrawer =
184
+ isAndroidChrome && consumerOverrides.drawer === undefined
185
+ ? { drawer: ['canvas', 'webgl', 'html'] }
186
+ : {};
176
187
 
177
188
  // Initialize OpenSeadragon viewer
178
189
  viewer = OSD({
@@ -188,8 +199,9 @@
188
199
  animationTime: 0.5,
189
200
  springStiffness: 7.0,
190
201
  zoomPerClick: 2.0,
202
+ ...defaultDrawer,
191
203
  // Consumer-provided OSD overrides
192
- ...(viewerState.config?.openSeadragonConfig ?? {}),
204
+ ...consumerOverrides,
193
205
  // Enable double-click to zoom, but keep clickToZoom disabled for Annotorious
194
206
  gestureSettingsMouse: {
195
207
  clickToZoom: false,
@@ -209,7 +221,9 @@
209
221
  viewer.viewport.minZoomLevel = homeZoom * floorFactor;
210
222
 
211
223
  if (overrides.minPixelRatio === undefined) {
212
- viewer.minPixelRatio = 0.5;
224
+ // Lower threshold prevents blanking on sparse/level-0 pyramids
225
+ // when zooming far out (especially on small mobile viewports).
226
+ viewer.minPixelRatio = 0.1;
213
227
  }
214
228
  });
215
229
 
@@ -344,29 +358,6 @@
344
358
  osd.__triiiceratopsIiifLevel0Patched = true;
345
359
  }
346
360
 
347
- function setViewerImageVisible(isVisible: boolean) {
348
- if (!container) return;
349
- container.style.opacity = isVisible ? '1' : '0';
350
- }
351
-
352
- function revealViewerImageAfterFirstRender(capturedKey: string) {
353
- if (!viewer) return;
354
-
355
- const reveal = () => {
356
- if (capturedKey !== lastTileSourceStr) return;
357
- setViewerImageVisible(true);
358
- };
359
-
360
- // WebGLDrawer in OSD 5 rejects tile-drawn/tile-drawing handlers.
361
- const drawerType = viewer.drawer?.getType?.();
362
- if (drawerType === 'webgl') {
363
- viewer.addOnceHandler('open', reveal);
364
- return;
365
- }
366
-
367
- viewer.addOnceHandler('tile-drawn', reveal);
368
- }
369
-
370
361
  // Pre-fetch info.json URLs to detect 401 auth errors before passing to OSD
371
362
  async function resolveTileSources(
372
363
  sources: any[],
@@ -415,7 +406,6 @@
415
406
  // If sources are cleared/absent during a canvas/world switch, clear
416
407
  // stale tiles immediately and allow the same source to reopen later.
417
408
  if (!tileSources) {
418
- setViewerImageVisible(false);
419
409
  viewer.close();
420
410
  viewerState.tileSourceError = null;
421
411
  lastTileSourceStr = '';
@@ -449,7 +439,6 @@
449
439
  : [];
450
440
 
451
441
  if (sources.length === 0) {
452
- setViewerImageVisible(false);
453
442
  viewer.close();
454
443
  viewerState.tileSourceError = null;
455
444
  lastTileSourceStr = '';
@@ -460,10 +449,6 @@
460
449
  const capturedKey = stateKey;
461
450
  const overrides = viewerState.config?.openSeadragonConfig ?? {};
462
451
 
463
- // Hide the previous image immediately; reveal once new tiles are drawn.
464
- setViewerImageVisible(false);
465
- revealViewerImageAfterFirstRender(capturedKey);
466
-
467
452
  if (mode === 'continuous') {
468
453
  // Remove current world immediately so stale canvases are not shown
469
454
  // while async source resolution is in progress.
@@ -471,7 +456,7 @@
471
456
  viewerState.tileSourceError = null;
472
457
 
473
458
  if (overrides.minPixelRatio === undefined) {
474
- viewer.minPixelRatio = 0.5;
459
+ viewer.minPixelRatio = 0.1;
475
460
  }
476
461
  if (overrides.minZoomImageRatio === undefined) {
477
462
  viewer.minZoomImageRatio = 0.9;
@@ -589,7 +574,7 @@
589
574
 
590
575
  // Restore less aggressive defaults outside continuous mode unless user-overridden.
591
576
  if (overrides.minPixelRatio === undefined) {
592
- viewer.minPixelRatio = 0.5;
577
+ viewer.minPixelRatio = 0.1;
593
578
  }
594
579
  if (overrides.minZoomImageRatio === undefined) {
595
580
  viewer.minZoomImageRatio = 0.9;
@@ -77,8 +77,12 @@ describe('ViewerState - IIIF Search', () => {
77
77
  * Helper to setup a mock manifest with canvases
78
78
  */
79
79
  function setupMockManifest(manifestJson) {
80
- const mockManifest = manifesto.parseManifest(manifestJson);
81
- const mockCanvases = mockManifest.getSequences()[0].getCanvases();
80
+ const parsed = manifesto.parseManifest(manifestJson);
81
+ if (!parsed) {
82
+ throw new Error('Failed to parse mock manifest');
83
+ }
84
+ const mockManifest = parsed;
85
+ const mockCanvases = mockManifest.getSequences()[0]?.getCanvases() ?? [];
82
86
  vi.mocked(manifestsState.getManifest).mockReturnValue(mockManifest);
83
87
  vi.mocked(manifestsState.getCanvases).mockReturnValue(mockCanvases);
84
88
  return { mockManifest, mockCanvases };