@papyrus-sdk/ui-react-native 0.2.35-beta.9 → 0.2.36
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.
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +829 -236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +843 -249
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -8
- package/runtime/epubAnnotations.js +276 -8
- package/runtime/epubReader.js +58 -0
- package/runtime/index.html +505 -84
- package/runtime/runtime.js +505 -84
- package/runtime/syncComicRuntime.mjs +6 -3
- package/runtime/comicRuntime.test.ts +0 -241
- package/runtime/documentLoadRuntime.test.ts +0 -172
- package/runtime/epubAnnotations.test.ts +0 -31
- package/runtime/epubScrollDiagnostics.test.ts +0 -107
- package/runtime/epubSelectionMenu.test.ts +0 -39
package/runtime/index.html
CHANGED
|
@@ -20483,6 +20483,67 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20483
20483
|
<!-- @papyrus-comic-runtime:end -->
|
|
20484
20484
|
<script>
|
|
20485
20485
|
(function () {
|
|
20486
|
+
/* @papyrus-epub-reader:start */
|
|
20487
|
+
(function(root){
|
|
20488
|
+
function mode(value){return value==='chapter-scroll'?'chapter-scroll':'paged';}
|
|
20489
|
+
function validCfi(value){return typeof value==='string' && value.length<=4096 && /^epubcfi\([^\n<>]+\)$/.test(value);}
|
|
20490
|
+
function options(value){return {manager:'default',flow:mode(value)==='paged'?'paginated':'scrolled-doc',spread:'none',width:'100%',height:'100%',allowScriptedContent:false};}
|
|
20491
|
+
function gesture(start,end,state){
|
|
20492
|
+
if(!start || !end || state.selected || state.interactive || state.multitouch)return null;
|
|
20493
|
+
var dx=end.x-start.x,dy=end.y-start.y,elapsed=end.time-start.time;
|
|
20494
|
+
if(state.mode==='paged' && Math.abs(dx)>=48 && Math.abs(dx)>Math.abs(dy)*1.5 && elapsed>=0 && elapsed<1500)return (dx<0)!==Boolean(state.rtl)?'next':'prev';
|
|
20495
|
+
if(elapsed>=0 && elapsed<450 && Math.hypot(dx,dy)<=12)return 'tap';
|
|
20496
|
+
return null;
|
|
20497
|
+
}
|
|
20498
|
+
function location(raw,count,readingMode,geometry){
|
|
20499
|
+
var start=raw && raw.start;if(!start || !validCfi(start.cfi))return null;
|
|
20500
|
+
var displayed=start.displayed||{},chapter=Math.max(1,(Number(start.index)||0)+1);
|
|
20501
|
+
var visualPage=mode(readingMode)==='paged' && Number.isFinite(displayed.page)?displayed.page:null;
|
|
20502
|
+
var total=mode(readingMode)==='paged' && Number.isFinite(displayed.total)?displayed.total:null;
|
|
20503
|
+
var atStart=Boolean(raw.atStart),atEnd=Boolean(raw.atEnd);
|
|
20504
|
+
// Chromium may round a column offset down by a fraction of a CSS pixel.
|
|
20505
|
+
// Keep epub.js authoritative outside a 1px boundary, and for RTL layouts.
|
|
20506
|
+
if(visualPage!==null && total>0 && geometry && geometry.direction==='ltr' && geometry.pageWidth>0 && Number.isFinite(geometry.offset)){
|
|
20507
|
+
var boundary=Math.round(geometry.offset/geometry.pageWidth);
|
|
20508
|
+
if(Math.abs(geometry.offset-boundary*geometry.pageWidth)<=1){
|
|
20509
|
+
visualPage=Math.min(total,Math.max(1,boundary+1));
|
|
20510
|
+
atStart=chapter===(geometry.firstIndex ?? 0)+1 && visualPage===1;
|
|
20511
|
+
atEnd=chapter===(geometry.lastIndex ?? count-1)+1 && visualPage===total;
|
|
20512
|
+
}
|
|
20513
|
+
}
|
|
20514
|
+
var fraction=total?Math.max(0,(visualPage-1)/total):0;
|
|
20515
|
+
return {version:1,cfi:start.cfi,href:start.href||'',chapter:chapter,chapterCount:count,visualPage:visualPage,visualPageCount:total,progress:Math.min(1,Math.max(0,(chapter-1+fraction)/Math.max(1,count))),mode:mode(readingMode),atStart:atStart,atEnd:atEnd};
|
|
20516
|
+
}
|
|
20517
|
+
function installResizeAnchor(manager,readCfi){
|
|
20518
|
+
var original=manager.resize,anchor=null;
|
|
20519
|
+
function resize(width,height,target){
|
|
20520
|
+
if(validCfi(target))anchor=target;
|
|
20521
|
+
if(!anchor){var current=readCfi();if(validCfi(current))anchor=current;}
|
|
20522
|
+
// epub.js accepts a logical target as its third argument. Keep it across
|
|
20523
|
+
// keyboard/dialog reflows instead of adopting each new viewport start.
|
|
20524
|
+
return original.call(this,width,height,anchor || target);
|
|
20525
|
+
}
|
|
20526
|
+
manager.resize=resize;
|
|
20527
|
+
return {cfi:function(){return anchor;},invalidate:function(){anchor=null;},destroy:function(){if(manager.resize===resize)manager.resize=original;anchor=null;}};
|
|
20528
|
+
}
|
|
20529
|
+
function install(contents,config){
|
|
20530
|
+
var doc=contents.document,win=contents.window,start=null,blocked=false;
|
|
20531
|
+
function point(e){var t=e.changedTouches&&e.changedTouches[0]||e.touches&&e.touches[0];return t?{x:t.clientX,y:t.clientY,time:Date.now()}:null;}
|
|
20532
|
+
function selected(){return Boolean(String(win.getSelection()||'').trim()) || config.blocked();}
|
|
20533
|
+
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay],[data-papyrus-ink-capture]'));}
|
|
20534
|
+
function begin(e){start=point(e);blocked=e.touches.length!==1 || selected() || interactive(e.target);}
|
|
20535
|
+
function invalidateScroll(finish){if(config.current() && start && finish && config.mode()==='chapter-scroll' && !blocked && !selected() && Math.abs(finish.y-start.y)>12 && Math.abs(finish.y-start.y)>Math.abs(finish.x-start.x) && config.interact)config.interact();}
|
|
20536
|
+
function move(e){if(e.touches.length!==1)blocked=true;invalidateScroll(point(e));}
|
|
20537
|
+
function end(e){var finish=point(e);invalidateScroll(finish);var action=gesture(start,finish,{mode:config.mode(),rtl:config.rtl(),selected:selected(),interactive:blocked||interactive(e.target)||Boolean(config.annotationHit && config.annotationHit(point(e))),multitouch:blocked});start=null;if(!config.current())return;if(action==='tap')config.tap();else if(action)config.turn(action==='next'?1:-1);}
|
|
20538
|
+
function cancel(){start=null;blocked=true;}
|
|
20539
|
+
function link(e){if(config.current() && e.target?.closest?.('a') && config.interact)config.interact();}
|
|
20540
|
+
doc.addEventListener('touchstart',begin,{passive:true});doc.addEventListener('touchmove',move,{passive:true});doc.addEventListener('touchend',end,{passive:true});doc.addEventListener('touchcancel',cancel,{passive:true});doc.addEventListener('click',link);
|
|
20541
|
+
return function(){doc.removeEventListener('touchstart',begin);doc.removeEventListener('touchmove',move);doc.removeEventListener('touchend',end);doc.removeEventListener('touchcancel',cancel);doc.removeEventListener('click',link);};
|
|
20542
|
+
}
|
|
20543
|
+
root.PapyrusEpubReader={mode:mode,validCfi:validCfi,options:options,gesture:gesture,location:location,installResizeAnchor:installResizeAnchor,install:install};
|
|
20544
|
+
})(typeof window==='undefined'?globalThis:window);
|
|
20545
|
+
|
|
20546
|
+
/* @papyrus-epub-reader:end */
|
|
20486
20547
|
/* @papyrus-epub-annotations:start */
|
|
20487
20548
|
(function (root, factory) {
|
|
20488
20549
|
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|
@@ -20494,6 +20555,84 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20494
20555
|
typeof anchor.href === 'string' && !/^(javascript|data):/i.test(anchor.href) &&
|
|
20495
20556
|
typeof anchor.quote === 'string' && anchor.quote.length > 0 && anchor.quote.length <= 100000;
|
|
20496
20557
|
}
|
|
20558
|
+
function simplifyPath(points, tolerance, maxPoints) {
|
|
20559
|
+
if (!Array.isArray(points) || points.length <= 2) return Array.isArray(points) ? points.slice() : [];
|
|
20560
|
+
tolerance = Number.isFinite(tolerance) ? Math.max(0, tolerance) : 1.5;
|
|
20561
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20562
|
+
var keep = new Uint8Array(points.length); keep[0] = 1; keep[points.length - 1] = 1;
|
|
20563
|
+
var stack = [[0, points.length - 1]], toleranceSquared = tolerance * tolerance;
|
|
20564
|
+
while (stack.length) {
|
|
20565
|
+
var interval = stack.pop(), first = interval[0], last = interval[1], a = points[first], b = points[last];
|
|
20566
|
+
var dx = b.x - a.x, dy = b.y - a.y, lengthSquared = dx * dx + dy * dy, maxDistance = toleranceSquared, split = -1;
|
|
20567
|
+
for (var i = first + 1; i < last; i++) {
|
|
20568
|
+
var p = points[i], ratio = lengthSquared ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared)) : 0;
|
|
20569
|
+
var px = a.x + ratio * dx, py = a.y + ratio * dy, ox = p.x - px, oy = p.y - py, distance = ox * ox + oy * oy;
|
|
20570
|
+
if (distance > maxDistance) { maxDistance = distance; split = i; }
|
|
20571
|
+
}
|
|
20572
|
+
if (split >= 0) { keep[split] = 1; stack.push([first, split], [split, last]); }
|
|
20573
|
+
}
|
|
20574
|
+
var result = []; for (var j = 0; j < points.length; j++) if (keep[j]) result.push(points[j]);
|
|
20575
|
+
if (result.length <= maxPoints) return result;
|
|
20576
|
+
var capped = []; for (var k = 0; k < maxPoints; k++) capped.push(result[Math.round(k * (result.length - 1) / (maxPoints - 1))]);
|
|
20577
|
+
return capped;
|
|
20578
|
+
}
|
|
20579
|
+
function compactGesturePoints(points, maxPoints) {
|
|
20580
|
+
if (!Array.isArray(points)) return [];
|
|
20581
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 1024;
|
|
20582
|
+
if (points.length <= maxPoints) return points.slice();
|
|
20583
|
+
var compacted = [];
|
|
20584
|
+
for (var i = 0; i < maxPoints; i++) compacted.push(points[Math.round(i * (points.length - 1) / (maxPoints - 1))]);
|
|
20585
|
+
return compacted;
|
|
20586
|
+
}
|
|
20587
|
+
function densifyPath(points, maxStep, maxPoints) {
|
|
20588
|
+
if (!Array.isArray(points) || !points.length) return [];
|
|
20589
|
+
if (points.length === 1) return points.slice();
|
|
20590
|
+
maxStep = Number.isFinite(maxStep) ? Math.max(1, maxStep) : 12;
|
|
20591
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20592
|
+
var cumulative = [0], total = 0;
|
|
20593
|
+
for (var i = 1; i < points.length; i++) {
|
|
20594
|
+
if (![points[i-1].x,points[i-1].y,points[i].x,points[i].y].every(Number.isFinite)) return [];
|
|
20595
|
+
total += Math.hypot(points[i].x-points[i-1].x, points[i].y-points[i-1].y);
|
|
20596
|
+
cumulative.push(total);
|
|
20597
|
+
}
|
|
20598
|
+
if (!total) return [points[0], points[points.length-1]];
|
|
20599
|
+
var intervals = Math.min(maxPoints-1, Math.max(1, Math.ceil(total/maxStep))), result = [], segment = 1;
|
|
20600
|
+
for (var sample = 0; sample <= intervals; sample++) {
|
|
20601
|
+
var distance = total*sample/intervals;
|
|
20602
|
+
while (segment < cumulative.length-1 && cumulative[segment] < distance) segment++;
|
|
20603
|
+
var start = points[segment-1], end = points[segment], span = cumulative[segment]-cumulative[segment-1];
|
|
20604
|
+
var ratio = span ? (distance-cumulative[segment-1])/span : 0;
|
|
20605
|
+
result.push({x:start.x+(end.x-start.x)*ratio,y:start.y+(end.y-start.y)*ratio});
|
|
20606
|
+
}
|
|
20607
|
+
return result;
|
|
20608
|
+
}
|
|
20609
|
+
function createSpatialIndex(entries, cellSize) {
|
|
20610
|
+
cellSize = Number.isFinite(cellSize) ? Math.max(8, cellSize) : 64;
|
|
20611
|
+
var cells = new Map();
|
|
20612
|
+
entries.forEach(function(entry) {
|
|
20613
|
+
var left = Math.floor(entry.left / cellSize), right = Math.floor(entry.right / cellSize);
|
|
20614
|
+
var top = Math.floor(entry.top / cellSize), bottom = Math.floor(entry.bottom / cellSize);
|
|
20615
|
+
for (var x = left; x <= right; x++) for (var y = top; y <= bottom; y++) {
|
|
20616
|
+
var key = x + ':' + y, bucket = cells.get(key); if (!bucket) { bucket = []; cells.set(key, bucket); } bucket.push(entry);
|
|
20617
|
+
}
|
|
20618
|
+
});
|
|
20619
|
+
return {cells:cells,cellSize:cellSize};
|
|
20620
|
+
}
|
|
20621
|
+
function queryNearestTextRect(index, x, y, maxDistance) {
|
|
20622
|
+
if (!index || !Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(maxDistance) || maxDistance < 0) return null;
|
|
20623
|
+
var size = index.cellSize, minX = Math.floor((x-maxDistance)/size), maxX = Math.floor((x+maxDistance)/size);
|
|
20624
|
+
var minY = Math.floor((y-maxDistance)/size), maxY = Math.floor((y+maxDistance)/size), seen = new Set(), best = null;
|
|
20625
|
+
for (var cx=minX; cx<=maxX; cx++) for (var cy=minY; cy<=maxY; cy++) {
|
|
20626
|
+
var bucket = index.cells.get(cx+':'+cy); if (!bucket) continue;
|
|
20627
|
+
bucket.forEach(function(entry) {
|
|
20628
|
+
if (seen.has(entry)) return; seen.add(entry);
|
|
20629
|
+
var nearestX = Math.max(entry.left,Math.min(entry.right,x)), nearestY = Math.max(entry.top,Math.min(entry.bottom,y));
|
|
20630
|
+
var dx=x-nearestX,dy=y-nearestY,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20631
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={entry:entry,distance:distance,x:nearestX,y:nearestY};
|
|
20632
|
+
});
|
|
20633
|
+
}
|
|
20634
|
+
return best;
|
|
20635
|
+
}
|
|
20497
20636
|
function textNodes(document) {
|
|
20498
20637
|
var walker = document.createTreeWalker(document.body, 4);
|
|
20499
20638
|
var nodes = [], text = '', node;
|
|
@@ -20543,13 +20682,196 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20543
20682
|
if(win.getComputedStyle(doc.body).position==='static')doc.body.style.position='relative';
|
|
20544
20683
|
doc.body.appendChild(overlay);
|
|
20545
20684
|
var registry = new Map(), hitRegions = [];
|
|
20685
|
+
var inkRegistry = new Map(), rangeCache = new Map(), spatialIndex = null, activeGesture = null, inkConfig = {enabled:false,preset:'ink'};
|
|
20686
|
+
var inkSvg = doc.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
20687
|
+
inkSvg.setAttribute('data-papyrus-ink-overlay','');
|
|
20688
|
+
inkSvg.style.cssText = 'position:absolute;left:0;top:0;overflow:visible;pointer-events:none;z-index:1';
|
|
20689
|
+
overlay.appendChild(inkSvg);
|
|
20690
|
+
var inkCanvas = doc.createElement('canvas');
|
|
20691
|
+
inkCanvas.dataset.papyrusInkCapture = '';
|
|
20692
|
+
inkCanvas.style.cssText = 'position:fixed;left:0;top:0;width:1px;height:1px;z-index:2147483000;background:transparent;pointer-events:none;touch-action:none';
|
|
20693
|
+
doc.body.appendChild(inkCanvas);
|
|
20694
|
+
var inkContext = null; try { if(typeof win.CanvasRenderingContext2D==='function')inkContext = inkCanvas.getContext('2d'); } catch (_) {}
|
|
20695
|
+
function resizeCanvas() {
|
|
20696
|
+
var bodyRect=doc.body.getBoundingClientRect(), ratio = Math.max(1,Math.min(3,win.devicePixelRatio || 1));
|
|
20697
|
+
var width=Math.max(1,Math.min(4096,doc.body.clientWidth||bodyRect.width||Math.min(4096,win.innerWidth||1)));
|
|
20698
|
+
var height=Math.max(1,Math.min(4096,doc.body.clientHeight||bodyRect.height||Math.min(4096,win.innerHeight||1)));
|
|
20699
|
+
inkCanvas.style.width=width+'px';inkCanvas.style.height=height+'px';
|
|
20700
|
+
inkCanvas.width = Math.round(width*ratio); inkCanvas.height = Math.round(height*ratio);
|
|
20701
|
+
if (inkContext) { inkContext.setTransform(ratio,0,0,ratio,0,0); inkContext.clearRect(0,0,width,height); }
|
|
20702
|
+
}
|
|
20703
|
+
function collectTextRects() {
|
|
20704
|
+
var walker = doc.createTreeWalker(doc.body,4), node, entries=[];
|
|
20705
|
+
while ((node=walker.nextNode())) {
|
|
20706
|
+
var parent=node.parentElement;
|
|
20707
|
+
if (!parent || parent.closest('script,style,noscript,textarea,[data-papyrus-overlay],[data-papyrus-ink-capture]')) continue;
|
|
20708
|
+
var text=node.nodeValue || '', style=win.getComputedStyle(parent), computed=parseFloat(style.lineHeight);
|
|
20709
|
+
for (var start=0; start<text.length;) {
|
|
20710
|
+
var end=Math.min(text.length,start+24), last=text.charCodeAt(end-1), next=text.charCodeAt(end);
|
|
20711
|
+
if(end<text.length&&last>=0xD800&&last<=0xDBFF&&next>=0xDC00&&next<=0xDFFF)end++;
|
|
20712
|
+
var range=doc.createRange(); range.setStart(node,start); range.setEnd(node,end);
|
|
20713
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20714
|
+
rects.forEach(function(rect) {
|
|
20715
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20716
|
+
entries.push({left:rect.left+win.scrollX,top:rect.top+win.scrollY,right:rect.right+win.scrollX,bottom:rect.bottom+win.scrollY,width:rect.width,height:rect.height,
|
|
20717
|
+
node:node,start:start,end:end,lineHeight:Number.isFinite(computed)&&computed>0?computed:rect.height});
|
|
20718
|
+
});
|
|
20719
|
+
start=end;
|
|
20720
|
+
}
|
|
20721
|
+
}
|
|
20722
|
+
return entries;
|
|
20723
|
+
}
|
|
20724
|
+
function rebuildSpatialIndex() { spatialIndex=createSpatialIndex(collectTextRects(),64); rangeCache.clear(); }
|
|
20725
|
+
function inkViewportExtent() {
|
|
20726
|
+
var root=doc.documentElement,body=doc.body,bodyRect=body.getBoundingClientRect();
|
|
20727
|
+
var width=root.clientWidth||body.clientWidth||bodyRect.width||win.innerWidth||1;
|
|
20728
|
+
var height=root.clientHeight||body.clientHeight||bodyRect.height||win.innerHeight||1;
|
|
20729
|
+
return Math.max(1,Math.min(4096,width),Math.min(4096,height));
|
|
20730
|
+
}
|
|
20731
|
+
function inkStrokeWidthPx(width,preset) {
|
|
20732
|
+
var scale=preset==='highlight'?0.8:preset==='underline'?0.1:0.15;
|
|
20733
|
+
return Math.max(1,Math.min(24,(Number.isFinite(width)?width:0.006)*inkViewportExtent()*scale));
|
|
20734
|
+
}
|
|
20735
|
+
function closestGlyph(entry,x,y,maxDistance) {
|
|
20736
|
+
var source=(entry.node.nodeValue || '').slice(entry.start,entry.end), best=null, offset=0;
|
|
20737
|
+
for (var glyph of source) {
|
|
20738
|
+
var range=doc.createRange(); range.setStart(entry.node,entry.start+offset); range.setEnd(entry.node,entry.start+offset+glyph.length); offset+=glyph.length;
|
|
20739
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20740
|
+
rects.forEach(function(rect) {
|
|
20741
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20742
|
+
var nx=Math.max(rect.left+win.scrollX,Math.min(rect.right+win.scrollX,x)), ny=Math.max(rect.top+win.scrollY,Math.min(rect.bottom+win.scrollY,y));
|
|
20743
|
+
var dx=x-nx,dy=y-ny,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20744
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={range:range,rect:rect,distance:distance};
|
|
20745
|
+
});
|
|
20746
|
+
}
|
|
20747
|
+
if (!best || typeof contents.cfiFromRange!=='function') return null;
|
|
20748
|
+
var quote=best.range.toString(), cfiRange; try { cfiRange=contents.cfiFromRange(best.range); } catch (_) { return null; }
|
|
20749
|
+
if (!quote || typeof cfiRange!=='string' || !/^epubcfi\([^\n<>]+\)$/.test(cfiRange)) return null;
|
|
20750
|
+
var lineHeight=Math.max(1,entry.lineHeight || best.rect.height), px=x-(best.rect.left+win.scrollX), py=y-(best.rect.top+win.scrollY);
|
|
20751
|
+
return {cfiRange:cfiRange,quote:quote,x:Math.max(-3,Math.min(3,px/lineHeight)),y:Math.max(-3,Math.min(3,py/lineHeight))};
|
|
20752
|
+
}
|
|
20753
|
+
function renderInkAnnotation(annotation,keep,bodyRect) {
|
|
20754
|
+
var baseRect=bodyRect || doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20755
|
+
var data=annotation.epubInk;
|
|
20756
|
+
if (!data || data.version!==1 || data.kind!=='epub-ink' || !Array.isArray(data.segments)) return;
|
|
20757
|
+
keep.add(annotation.id);
|
|
20758
|
+
var group=inkRegistry.get(annotation.id);
|
|
20759
|
+
if (!group) { group=doc.createElementNS('http://www.w3.org/2000/svg','g'); group.setAttribute('data-epub-ink-id',annotation.id); inkSvg.appendChild(group); inkRegistry.set(annotation.id,group); }
|
|
20760
|
+
group.replaceChildren();
|
|
20761
|
+
var color=/^#[0-9a-f]{6}$/i.test(annotation.color)?annotation.color:'#2563eb';
|
|
20762
|
+
var opacity=Number.isFinite(annotation.opacity)?Math.max(0,Math.min(1,annotation.opacity)):1;
|
|
20763
|
+
var preset=['ink','highlight','underline'].indexOf(data.preset)>=0?data.preset:'ink';
|
|
20764
|
+
var stroke=inkStrokeWidthPx(annotation.strokeWidth,preset);
|
|
20765
|
+
data.segments.forEach(function(segment) {
|
|
20766
|
+
if (segment.href!==options.href || !Array.isArray(segment.points)) return;
|
|
20767
|
+
var paths=[], current=[];
|
|
20768
|
+
segment.points.forEach(function(point) {
|
|
20769
|
+
var range=rangeCache.get(point.cfiRange);
|
|
20770
|
+
if (!range) { try { range=contents.range(point.cfiRange); } catch (_) { range=null; } if (range) rangeCache.set(point.cfiRange,range); }
|
|
20771
|
+
if (!range || range.toString()!==point.quote) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20772
|
+
var rect; try { rect=range.getBoundingClientRect(); } catch (_) { rect=null; }
|
|
20773
|
+
if (!rect || !(rect.width>0 && rect.height>0)) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20774
|
+
var lineHeight=Math.max(1,rect.height), x=rect.left-baseRect.left+point.x*lineHeight, y=rect.top-baseRect.top+point.y*lineHeight;
|
|
20775
|
+
var previous=current[current.length-1], jumpLimit=Math.max(24,lineHeight*2.5);
|
|
20776
|
+
if (previous && Math.hypot(x-previous.x,y-previous.y)>jumpLimit) { if(current.length>1)paths.push(current);current=[]; }
|
|
20777
|
+
current.push({x:x,y:y,lineHeight:lineHeight});
|
|
20778
|
+
});
|
|
20779
|
+
if(current.length>1)paths.push(current);
|
|
20780
|
+
paths.forEach(function(points) {
|
|
20781
|
+
var d='M '+points[0].x.toFixed(1)+' '+points[0].y.toFixed(1);
|
|
20782
|
+
for(var i=1;i<points.length;i++){var prev=points[i-1],point=points[i],mx=(prev.x+point.x)/2,my=(prev.y+point.y)/2;d+=' Q '+prev.x.toFixed(1)+' '+prev.y.toFixed(1)+' '+mx.toFixed(1)+' '+my.toFixed(1);}
|
|
20783
|
+
var last=points[points.length-1];d+=' L '+last.x.toFixed(1)+' '+last.y.toFixed(1);
|
|
20784
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');path.setAttribute('d',d);path.setAttribute('fill','none');path.setAttribute('stroke',color);path.setAttribute('stroke-width',String(stroke));path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(opacity));group.appendChild(path);
|
|
20785
|
+
});
|
|
20786
|
+
});
|
|
20787
|
+
}
|
|
20788
|
+
function clearPreview() {
|
|
20789
|
+
if(inkContext)inkContext.clearRect(0,0,inkCanvas.width,inkCanvas.height);
|
|
20790
|
+
inkSvg.querySelectorAll('[data-papyrus-ink-preview]').forEach(function(path){path.remove();});
|
|
20791
|
+
}
|
|
20792
|
+
function createPreviewPath(x,y) {
|
|
20793
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');
|
|
20794
|
+
path.setAttribute('data-papyrus-ink-preview','');path.setAttribute('d','M '+x.toFixed(1)+' '+y.toFixed(1));path.setAttribute('fill','none');
|
|
20795
|
+
path.setAttribute('stroke',inkConfig.color);path.setAttribute('stroke-width',String(inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset)));
|
|
20796
|
+
path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(inkConfig.opacity));
|
|
20797
|
+
path.style.pointerEvents='none';inkSvg.appendChild(path);return path;
|
|
20798
|
+
}
|
|
20799
|
+
function updatePreviewPath(clientX,clientY) {
|
|
20800
|
+
var bodyRect=doc.body.getBoundingClientRect(),x=clientX-bodyRect.left,y=clientY-bodyRect.top;
|
|
20801
|
+
var gesture=activeGesture;
|
|
20802
|
+
if(!gesture.previewPath||gesture.previewPathPoints>=32){
|
|
20803
|
+
gesture.previewPath=createPreviewPath(gesture.previewLast?gesture.previewLast.x:x,gesture.previewLast?gesture.previewLast.y:y);
|
|
20804
|
+
gesture.previewPathPoints=1;
|
|
20805
|
+
}
|
|
20806
|
+
var pathData=gesture.previewPath.getAttribute('d')||'';
|
|
20807
|
+
gesture.previewPath.setAttribute('d',pathData+' L '+x.toFixed(1)+' '+y.toFixed(1));
|
|
20808
|
+
gesture.previewPathPoints++;
|
|
20809
|
+
gesture.previewLast={x:x,y:y};
|
|
20810
|
+
}
|
|
20811
|
+
function cancelGesture() {
|
|
20812
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20813
|
+
if(gesture)try{inkCanvas.releasePointerCapture(gesture.pointerId);}catch(_){}
|
|
20814
|
+
}
|
|
20815
|
+
function commitGesture() {
|
|
20816
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20817
|
+
if(!gesture || !alive || !options.isCurrent() || !inkConfig.enabled || !spatialIndex) return;
|
|
20818
|
+
var simplified=simplifyPath(gesture.points,1.5,512), anchorSamples=densifyPath(simplified,12,512), segments=[], current=[];
|
|
20819
|
+
anchorSamples.forEach(function(point) {
|
|
20820
|
+
var coarse=queryNearestTextRect(spatialIndex,point.x,point.y,28);
|
|
20821
|
+
var cutoff=coarse?Math.max(12,Math.min(28,0.8*coarse.entry.lineHeight)):12;
|
|
20822
|
+
var anchored=coarse && closestGlyph(coarse.entry,point.x,point.y,cutoff);
|
|
20823
|
+
if(!anchored){if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});current=[];return;}
|
|
20824
|
+
current.push(anchored);
|
|
20825
|
+
});
|
|
20826
|
+
if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});
|
|
20827
|
+
segments=segments.slice(0,64);
|
|
20828
|
+
var pointCount=segments.reduce(function(total,segment){return total+segment.points.length;},0);
|
|
20829
|
+
if(!pointCount)return;
|
|
20830
|
+
var width=Math.max(1,doc.documentElement.scrollWidth,win.innerWidth),height=Math.max(1,doc.documentElement.scrollHeight,win.innerHeight);
|
|
20831
|
+
var normalized=simplified.map(function(p){return {x:Math.max(0,Math.min(1,p.x/width)),y:Math.max(0,Math.min(1,p.y/height))};});
|
|
20832
|
+
var minX=Math.min.apply(null,normalized.map(function(p){return p.x;})),maxX=Math.max.apply(null,normalized.map(function(p){return p.x;}));
|
|
20833
|
+
var minY=Math.min.apply(null,normalized.map(function(p){return p.y;})),maxY=Math.max.apply(null,normalized.map(function(p){return p.y;}));
|
|
20834
|
+
var first=segments[0].points[0], href=segments[0].href, documentId=typeof options.documentId==='function'?options.documentId():options.documentId;
|
|
20835
|
+
var annotation={id:'epub-ink-'+Date.now()+'-'+Math.random().toString(36).slice(2,9),type:'ink',pageIndex:(options.spineIndex||0)+1,
|
|
20836
|
+
rect:{x:minX,y:minY,width:Math.min(1-minX,Math.max(0.001,maxX-minX)),height:Math.min(1-minY,Math.max(0.001,maxY-minY))},path:normalized,color:inkConfig.color,opacity:inkConfig.opacity,strokeWidth:inkConfig.strokeWidth,createdAt:Date.now(),content:first.quote,
|
|
20837
|
+
anchor:{version:1,kind:'epub-cfi',cfiRange:first.cfiRange,href:href,spineIndex:options.spineIndex,documentId:documentId,quote:first.quote},
|
|
20838
|
+
epubInk:{version:1,kind:'epub-ink',documentId:documentId,preset:inkConfig.preset,segments:segments}};
|
|
20839
|
+
if(typeof options.onInkCommit==='function')options.onInkCommit(annotation);
|
|
20840
|
+
}
|
|
20841
|
+
function pointerDown(event) {
|
|
20842
|
+
if(!inkConfig.enabled || !alive || !options.isCurrent() || event.button!==undefined && event.button!==0)return;
|
|
20843
|
+
if(activeGesture){cancelGesture();return;}
|
|
20844
|
+
event.preventDefault();event.stopPropagation();
|
|
20845
|
+
activeGesture={pointerId:event.pointerId,points:[{x:event.clientX+win.scrollX,y:event.clientY+win.scrollY}],last:{x:event.clientX,y:event.clientY},previewPath:null,previewPathPoints:0,previewLast:null};
|
|
20846
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20847
|
+
try{inkCanvas.setPointerCapture(event.pointerId);}catch(_){}
|
|
20848
|
+
}
|
|
20849
|
+
function pointerMove(event) {
|
|
20850
|
+
if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;
|
|
20851
|
+
if(!options.isCurrent()||!inkConfig.enabled){cancelGesture();return;}
|
|
20852
|
+
event.preventDefault();event.stopPropagation();
|
|
20853
|
+
var point={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY};activeGesture.points.push(point);
|
|
20854
|
+
if(activeGesture.points.length>2048)activeGesture.points=compactGesturePoints(activeGesture.points,1024);
|
|
20855
|
+
if(inkContext){inkContext.beginPath();inkContext.moveTo(activeGesture.last.x,activeGesture.last.y);inkContext.lineTo(event.clientX,event.clientY);inkContext.strokeStyle=inkConfig.color;inkContext.globalAlpha=inkConfig.opacity;inkContext.lineWidth=inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset);inkContext.lineCap='round';inkContext.lineJoin='round';inkContext.stroke();}
|
|
20856
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20857
|
+
activeGesture.last={x:event.clientX,y:event.clientY};
|
|
20858
|
+
}
|
|
20859
|
+
function pointerUp(event) {if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;event.preventDefault();event.stopPropagation();var end={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY},last=activeGesture.points[activeGesture.points.length-1];if(Math.hypot(end.x-last.x,end.y-last.y)>0.5){activeGesture.points.push(end);updatePreviewPath(event.clientX,event.clientY);}commitGesture();}
|
|
20860
|
+
function pointerCancel(event) {if(activeGesture && (event.pointerId===undefined || activeGesture.pointerId===event.pointerId))cancelGesture();}
|
|
20861
|
+
resizeCanvas();rebuildSpatialIndex();
|
|
20862
|
+
inkCanvas.addEventListener('pointerdown',pointerDown);inkCanvas.addEventListener('pointermove',pointerMove);inkCanvas.addEventListener('pointerup',pointerUp);inkCanvas.addEventListener('pointercancel',pointerCancel);inkCanvas.addEventListener('lostpointercapture',pointerCancel);
|
|
20863
|
+
win.addEventListener('blur',pointerCancel);win.addEventListener('resize',resizeCanvas);
|
|
20546
20864
|
function render() {
|
|
20547
20865
|
frame = 0; if (!alive || !options.isCurrent()) return;
|
|
20548
|
-
var keep = new Set(), noteGroups = new Map();
|
|
20866
|
+
var keep = new Set(), keepInk = new Set(), noteGroups = new Map();
|
|
20549
20867
|
hitRegions = [];
|
|
20868
|
+
var bodyRect=doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20869
|
+
inkSvg.setAttribute('width',String(Math.max(doc.documentElement.scrollWidth,win.innerWidth)));
|
|
20870
|
+
inkSvg.setAttribute('height',String(Math.max(doc.documentElement.scrollHeight,win.innerHeight)));
|
|
20550
20871
|
options.annotations().forEach(function(annotation) {
|
|
20551
20872
|
var anchor = annotation.anchor;
|
|
20552
20873
|
if (!validAnchor(anchor) || anchor.href !== options.href || anchor.documentId && options.documentId && anchor.documentId !== options.documentId) return;
|
|
20874
|
+
if(annotation.type==='ink' && annotation.epubInk){renderInkAnnotation(annotation,keepInk,bodyRect);return;}
|
|
20553
20875
|
var range = resolveRange(contents,anchor); if (!range) return;
|
|
20554
20876
|
var rects = Array.from(range.getClientRects()).filter(function(r){return r.width>0 && r.height>0;});
|
|
20555
20877
|
if (!rects.length) return;
|
|
@@ -20561,6 +20883,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20561
20883
|
var color = /^#[0-9a-f]{6}$/i.test(annotation.color) ? annotation.color : '#FFC928';
|
|
20562
20884
|
var style = annotation.markupStyle || annotation.type;
|
|
20563
20885
|
var opacity = Number.isFinite(annotation.opacity) ? Math.max(0,Math.min(1,annotation.opacity)) : 0.35;
|
|
20886
|
+
if(style === 'highlight')opacity=Math.min(0.35,opacity);
|
|
20564
20887
|
rects.forEach(function(rect) {
|
|
20565
20888
|
var mark = doc.createElement('div');
|
|
20566
20889
|
var bodyRect=doc.body.getBoundingClientRect();
|
|
@@ -20573,8 +20896,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20573
20896
|
if (hasNote) {
|
|
20574
20897
|
var last = rects[rects.length-1], button = doc.createElement('button');
|
|
20575
20898
|
button.textContent = '●'; button.setAttribute('aria-label',options.labels().comment || '');
|
|
20576
|
-
|
|
20577
|
-
var
|
|
20899
|
+
var pageWidth=Math.max(44, options.pageWidth ? options.pageWidth() : win.innerWidth);
|
|
20900
|
+
var bodyRect=doc.body.getBoundingClientRect(), column=Math.max(0,Math.floor((last.left-bodyRect.left)/pageWidth));
|
|
20901
|
+
button.style.cssText = 'position:absolute;pointer-events:auto;border:0;background:transparent;color:'+color+';width:44px;height:44px;left:'+((column+1)*pageWidth-44)+'px;top:'+(Math.floor(last.top/44)*44-doc.body.getBoundingClientRect().top)+'px';
|
|
20902
|
+
var key = column+":"+Math.floor(last.top/44);
|
|
20578
20903
|
var neighbors=noteGroups.get(key);
|
|
20579
20904
|
if(!neighbors){neighbors={button:button,ids:[]};noteGroups.set(key,neighbors);group.appendChild(button);}
|
|
20580
20905
|
neighbors.ids.push(annotation.id);
|
|
@@ -20585,22 +20910,26 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20585
20910
|
group.button.addEventListener('click',function(e){e.stopPropagation();if(options.isCurrent())options.onTap(group.ids[0],group.ids);});
|
|
20586
20911
|
});
|
|
20587
20912
|
registry.forEach(function(group,id){if (!keep.has(id)) {group.remove();registry.delete(id);}});
|
|
20913
|
+
inkRegistry.forEach(function(group,id){if (!keepInk.has(id)) {group.remove();inkRegistry.delete(id);}});
|
|
20588
20914
|
}
|
|
20589
20915
|
function schedule() { if (alive && !frame) frame = win.requestAnimationFrame(render); }
|
|
20916
|
+
function rebuildAndSchedule(){if(!alive)return;rebuildSpatialIndex();schedule();}
|
|
20917
|
+
function handleResize(){resizeCanvas();rebuildAndSchedule();}
|
|
20918
|
+
function handleDocumentLoad(){rebuildAndSchedule();}
|
|
20590
20919
|
function tapMarkup(event) {
|
|
20591
20920
|
if(!alive || !options.isCurrent() || String(win.getSelection() || '').length || event.target.closest('[data-papyrus-overlay]'))return;
|
|
20592
20921
|
var hit=hitRegions.find(function(item){return item.rects.some(function(r){return event.clientX>=r.left && event.clientX<=r.right && event.clientY>=r.top && event.clientY<=r.bottom;});});
|
|
20593
20922
|
if(hit) {event.stopPropagation();options.onTap(hit.id);}
|
|
20594
20923
|
}
|
|
20595
20924
|
doc.addEventListener('click',tapMarkup);
|
|
20596
|
-
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(
|
|
20925
|
+
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(rebuildAndSchedule) : null;
|
|
20597
20926
|
if (observer) observer.observe(doc.body);
|
|
20598
|
-
win.addEventListener('resize',schedule); doc.addEventListener('load',
|
|
20599
|
-
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20927
|
+
win.addEventListener('resize',handleResize);win.addEventListener('scroll',schedule); doc.addEventListener('load',handleDocumentLoad,true);
|
|
20928
|
+
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(function(){if(alive){rebuildSpatialIndex();schedule();}});
|
|
20600
20929
|
schedule();
|
|
20601
|
-
return {schedule:schedule, range:function(anchor){return resolveRange(contents,anchor);}, destroy:function(){alive=false;if(frame)win.cancelAnimationFrame(frame);if(observer)observer.disconnect();win.removeEventListener('resize',schedule);doc.removeEventListener('load',
|
|
20930
|
+
return {schedule:schedule, setInkMode:function(config){var preset=['ink','highlight','underline'].indexOf(config?.preset)>=0?config.preset:'ink';inkConfig={enabled:!!config?.enabled,preset:preset,color:/^#[0-9a-f]{6}$/i.test(config?.color)?config.color:'#2563eb',opacity:Number.isFinite(config?.opacity)?Math.max(0,Math.min(1,config.opacity)):1,strokeWidth:Number.isFinite(config?.strokeWidth)?Math.max(0.0025,Math.min(0.02,config.strokeWidth)):0.006};inkCanvas.style.pointerEvents=inkConfig.enabled?'auto':'none';if(!inkConfig.enabled)cancelGesture();}, invalidateLayout:rebuildAndSchedule, hit:function(x,y){return hitRegions.some(function(item){return item.rects.some(function(r){return x>=r.left && x<=r.right && y>=r.top && y<=r.bottom;});});}, range:function(anchor){return resolveRange(contents,anchor);}, destroy:function(){alive=false;cancelGesture();if(frame)win.cancelAnimationFrame(frame);if(observer)observer.disconnect();win.removeEventListener('resize',handleResize);win.removeEventListener('scroll',schedule);win.removeEventListener('blur',pointerCancel);doc.removeEventListener('load',handleDocumentLoad,true);doc.removeEventListener('click',tapMarkup);inkCanvas.removeEventListener('pointerdown',pointerDown);inkCanvas.removeEventListener('pointermove',pointerMove);inkCanvas.removeEventListener('pointerup',pointerUp);inkCanvas.removeEventListener('pointercancel',pointerCancel);inkCanvas.removeEventListener('lostpointercapture',pointerCancel);inkCanvas.remove();overlay.remove();doc.body.style.position=originalPosition;registry.clear();inkRegistry.clear();rangeCache.clear();}};
|
|
20602
20931
|
}
|
|
20603
|
-
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20932
|
+
return {validAnchor:validAnchor,simplifyPath:simplifyPath,compactGesturePoints:compactGesturePoints,densifyPath:densifyPath,createSpatialIndex:createSpatialIndex,queryNearestTextRect:queryNearestTextRect,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20604
20933
|
});
|
|
20605
20934
|
|
|
20606
20935
|
/* @papyrus-epub-annotations:end */
|
|
@@ -20611,10 +20940,12 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20611
20940
|
let currentType = null;
|
|
20612
20941
|
let book = null;
|
|
20613
20942
|
let rendition = null;
|
|
20943
|
+
let epubResizeAnchor = null;
|
|
20614
20944
|
let documentSessionId = null;
|
|
20615
20945
|
let annotationDocumentId;
|
|
20616
20946
|
let annotationLabels = {};
|
|
20617
20947
|
let epubAnnotations = [];
|
|
20948
|
+
let epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
20618
20949
|
const epubAnnotationRenderers = new Map();
|
|
20619
20950
|
let spineItems = [];
|
|
20620
20951
|
let textPages = [];
|
|
@@ -21023,6 +21354,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21023
21354
|
};
|
|
21024
21355
|
|
|
21025
21356
|
const clearViewer = () => {
|
|
21357
|
+
if(epubResizeAnchor){epubResizeAnchor.destroy();epubResizeAnchor=null;}
|
|
21026
21358
|
epubAnnotationRenderers.forEach(renderer => renderer.destroy());
|
|
21027
21359
|
epubAnnotationRenderers.clear();
|
|
21028
21360
|
if (epubInteractionCleanup) {
|
|
@@ -21679,29 +22011,63 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21679
22011
|
pageCount,
|
|
21680
22012
|
});
|
|
21681
22013
|
|
|
22014
|
+
if (book.locations?.generate) {
|
|
22015
|
+
const activeBook=book;
|
|
22016
|
+
activeBook.locations.generate(150).then(() => {
|
|
22017
|
+
if (isCurrentLoad() && activeBook===book && epubLocation) {
|
|
22018
|
+
epubLocation.progress=activeBook.locations.percentageFromCfi(epubLocation.cfi);
|
|
22019
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
22020
|
+
}
|
|
22021
|
+
}).catch(() => {});
|
|
22022
|
+
}
|
|
22023
|
+
return renderEpubRendition(loadId,generation,null);
|
|
22024
|
+
};
|
|
22025
|
+
|
|
22026
|
+
const renderEpubRendition = async (loadId,generation,target) => {
|
|
22027
|
+
const diagnosticPayload={loadId};
|
|
22028
|
+
const isCurrentLoad=()=>generation===epubLoadGeneration;
|
|
22029
|
+
if(epubInteractionCleanup)epubInteractionCleanup();
|
|
22030
|
+
if(rendition)rendition.destroy();
|
|
21682
22031
|
clearViewer();
|
|
21683
|
-
rendition = book.renderTo(viewer,
|
|
21684
|
-
manager: 'continuous',
|
|
21685
|
-
allowScriptedContent: false,
|
|
21686
|
-
width: '100%',
|
|
21687
|
-
height: '100%',
|
|
21688
|
-
flow: 'scrolled-continuous',
|
|
21689
|
-
spread: 'none',
|
|
21690
|
-
});
|
|
22032
|
+
rendition = book.renderTo(viewer, window.PapyrusEpubReader.options(epubViewMode === 'single' ? 'paged' : 'chapter-scroll'));
|
|
21691
22033
|
sendEpubDiagnostic('epub.rendition.created', diagnosticPayload);
|
|
21692
22034
|
|
|
21693
22035
|
if (rendition && rendition.hooks && rendition.hooks.content) {
|
|
21694
22036
|
const session = documentSessionId;
|
|
21695
22037
|
const activeRendition = rendition;
|
|
21696
22038
|
rendition.hooks.content.register((contents) => {
|
|
22039
|
+
const removeGestureListeners = window.PapyrusEpubReader.install(contents, {
|
|
22040
|
+
mode: () => epubViewMode === 'single' ? 'paged' : 'chapter-scroll',
|
|
22041
|
+
rtl: () => book.package?.metadata?.direction === 'rtl' || book.spine?.direction === 'rtl',
|
|
22042
|
+
blocked: () => Boolean(nativeMenuSelection && String(nativeMenuSelection.contents?.window?.getSelection() || '').trim()),
|
|
22043
|
+
annotationHit: point => epubAnnotationRenderers.get(contents)?.hit(point.x,point.y),
|
|
22044
|
+
current: () => session === documentSessionId && activeRendition === rendition,
|
|
22045
|
+
interact: () => epubResizeAnchor?.invalidate(),
|
|
22046
|
+
tap: () => sendEvent('EPUB_CONTENT_TAP',{documentSessionId:session}),
|
|
22047
|
+
turn: direction => {
|
|
22048
|
+
epubNavigationQueue = epubNavigationQueue.catch(()=>{}).then(() => {
|
|
22049
|
+
if(session !== documentSessionId || activeRendition !== rendition)return;
|
|
22050
|
+
epubResizeAnchor?.invalidate();
|
|
22051
|
+
return direction<0?activeRendition.prev():activeRendition.next();
|
|
22052
|
+
});
|
|
22053
|
+
epubNavigationQueue.catch(error => sendEvent('EPUB_NAVIGATION_ERROR',{message:String(error)}));
|
|
22054
|
+
},
|
|
22055
|
+
});
|
|
22056
|
+
const gestureCleanup = () => {removeGestureListeners();epubSelectionCleanups.delete(gestureCleanup);};
|
|
22057
|
+
epubSelectionCleanups.add(gestureCleanup);
|
|
22058
|
+
contents.__papyrusGestureCleanup=gestureCleanup;
|
|
21697
22059
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21698
22060
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21699
22061
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21700
22062
|
href, get documentId() { return annotationDocumentId; },
|
|
22063
|
+
spineIndex:contents.sectionIndex,
|
|
21701
22064
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
22065
|
+
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21702
22066
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
22067
|
+
onInkCommit: annotation => sendEvent('EPUB_INK_CREATED',{documentSessionId:session,annotation}),
|
|
21703
22068
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21704
22069
|
});
|
|
22070
|
+
renderer.setInkMode(epubInkMode);
|
|
21705
22071
|
epubAnnotationRenderers.set(contents,renderer);
|
|
21706
22072
|
}
|
|
21707
22073
|
const frame = contents && contents.document ? contents.document.defaultView.frameElement : null;
|
|
@@ -21717,8 +22083,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21717
22083
|
typeof selectionWindow.getSelection === 'function'
|
|
21718
22084
|
) {
|
|
21719
22085
|
let selectionTimer = null;
|
|
21720
|
-
|
|
21721
|
-
let lastSelectionAt = 0;
|
|
22086
|
+
|
|
21722
22087
|
const reportSelection = () => {
|
|
21723
22088
|
selectionTimer = null;
|
|
21724
22089
|
if (session !== documentSessionId || activeRendition !== rendition) return;
|
|
@@ -21733,11 +22098,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21733
22098
|
try { cfi = contents.cfiFromRange(range); } catch (_) { return; }
|
|
21734
22099
|
const anchor = window.PapyrusEpubAnnotations?.selection(contents, cfi, href, annotationDocumentId);
|
|
21735
22100
|
if (!anchor) return;
|
|
21736
|
-
|
|
21737
|
-
const now = Date.now();
|
|
21738
|
-
if (key === lastSelectionKey && now - lastSelectionAt < 750) return;
|
|
21739
|
-
lastSelectionKey = key;
|
|
21740
|
-
lastSelectionAt = now;
|
|
22101
|
+
if (nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21741
22102
|
const payload = {documentSessionId: session, text: anchor.quote,
|
|
21742
22103
|
pageIndex: contents.sectionIndex + 1, anchor};
|
|
21743
22104
|
nativeMenuSelection = {contents, payload};
|
|
@@ -21752,6 +22113,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21752
22113
|
// The content document still emits selectionchange, so resolve its
|
|
21753
22114
|
// live Range to a CFI before the native menu action can fire.
|
|
21754
22115
|
if (text) reportSelection();
|
|
22116
|
+
else if (nativeMenuSelection?.contents === contents) nativeMenuSelection = null;
|
|
21755
22117
|
};
|
|
21756
22118
|
selectionDocument.addEventListener('selectionchange', handleSelectionChange);
|
|
21757
22119
|
const selectionCleanup = () => {
|
|
@@ -21774,6 +22136,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21774
22136
|
typeof rendition.hooks.unloaded.register === 'function'
|
|
21775
22137
|
) {
|
|
21776
22138
|
rendition.hooks.unloaded.register((view) => {
|
|
22139
|
+
view?.contents?.__papyrusGestureCleanup?.();
|
|
21777
22140
|
const cleanup = view && view.contents && view.contents.__papyrusSelectionCleanup;
|
|
21778
22141
|
if (typeof cleanup === 'function') cleanup();
|
|
21779
22142
|
const renderer = epubAnnotationRenderers.get(view?.contents);
|
|
@@ -21789,21 +22152,37 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21789
22152
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
21790
22153
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21791
22154
|
const anchor = href && window.PapyrusEpubAnnotations?.selection(contents,cfiRange,href,annotationDocumentId);
|
|
21792
|
-
if (!anchor) return;
|
|
22155
|
+
if (!anchor || nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21793
22156
|
epubScrollDiagnostics && epubScrollDiagnostics.setSelectionActive(true);
|
|
21794
22157
|
const payload = {documentSessionId: selectionSession, text: anchor.quote, pageIndex: contents.sectionIndex+1, anchor};
|
|
21795
22158
|
nativeMenuSelection = {contents, payload};
|
|
21796
22159
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21797
22160
|
});
|
|
21798
|
-
['rendered','resized','layout'].forEach(name => rendition.on(name, () => {
|
|
21799
|
-
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22161
|
+
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
22162
|
+
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => name==='relocated'?renderer.schedule():renderer.invalidateLayout());
|
|
21800
22163
|
}));
|
|
21801
22164
|
rendition.on('relocated', (location) => {
|
|
22165
|
+
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
21802
22166
|
const start = location && location.start;
|
|
21803
22167
|
let index = start && Number.isInteger(start.index) ? start.index : -1;
|
|
21804
22168
|
if (index < 0 && start && start.href) index = getSpineIndexByHref(start.href);
|
|
21805
22169
|
if (index < 0 || index >= spineItems.length) return;
|
|
21806
22170
|
epubScrollDiagnostics && epubScrollDiagnostics.relocated(location);
|
|
22171
|
+
let pageGeometry;
|
|
22172
|
+
const manager=rendition.manager,layout=manager?.layout;
|
|
22173
|
+
if(epubViewMode==='single' && layout?.divisor===1 && !manager?.settings?.fullsize && manager?.settings?.direction==='ltr'){
|
|
22174
|
+
const visible=manager.visible?.();
|
|
22175
|
+
const view=visible?.find(view=>view.index===index);
|
|
22176
|
+
if(view && manager.container){
|
|
22177
|
+
pageGeometry={direction:'ltr',firstIndex:book.spine.first()?.index,lastIndex:book.spine.last()?.index,pageWidth:layout.pageWidth,offset:manager.container.getBoundingClientRect().left-view.position().left};
|
|
22178
|
+
}
|
|
22179
|
+
}
|
|
22180
|
+
epubLocation=window.PapyrusEpubReader.location(location,spineItems.length,epubViewMode==='single'?'paged':'chapter-scroll',pageGeometry);
|
|
22181
|
+
if(epubLocation){
|
|
22182
|
+
epubLocation.cfi=epubResizeAnchor?.cfi() || epubLocation.cfi;
|
|
22183
|
+
if(book.locations?.length?.()>0)epubLocation.progress=book.locations.percentageFromCfi(epubLocation.cfi);
|
|
22184
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
22185
|
+
}
|
|
21807
22186
|
const nextPage = index + 1;
|
|
21808
22187
|
if (nextPage === currentPage) return;
|
|
21809
22188
|
currentPage = nextPage;
|
|
@@ -21811,21 +22190,23 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21811
22190
|
});
|
|
21812
22191
|
}
|
|
21813
22192
|
|
|
22193
|
+
applyEpubZoom();
|
|
21814
22194
|
sendEpubDiagnostic('epub.display.start', diagnosticPayload);
|
|
21815
22195
|
await withEpubStageTimeout(
|
|
21816
|
-
|
|
22196
|
+
rendition.display(target || spineItems[0]?.href),
|
|
21817
22197
|
'rendition.display',
|
|
21818
22198
|
diagnosticPayload,
|
|
21819
22199
|
);
|
|
21820
22200
|
if (!isCurrentLoad()) throw new Error('EPUB load superseded by a newer load');
|
|
21821
22201
|
sendEpubDiagnostic('epub.display.end', diagnosticPayload);
|
|
22202
|
+
const resizeRendition=rendition;
|
|
22203
|
+
epubResizeAnchor=window.PapyrusEpubReader.installResizeAnchor(resizeRendition.manager,()=>resizeRendition.location?.start?.cfi);
|
|
21822
22204
|
if (
|
|
21823
22205
|
rendition &&
|
|
21824
22206
|
rendition.manager &&
|
|
21825
22207
|
typeof rendition.manager.on === 'function' &&
|
|
21826
22208
|
typeof rendition.on === 'function'
|
|
21827
22209
|
) {
|
|
21828
|
-
let touchStart = null;
|
|
21829
22210
|
let lastScrollOffset = -1;
|
|
21830
22211
|
const manager = rendition.manager;
|
|
21831
22212
|
epubScrollDiagnostics = createEpubScrollDiagnostics(manager);
|
|
@@ -21900,48 +22281,19 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21900
22281
|
return result;
|
|
21901
22282
|
};
|
|
21902
22283
|
}
|
|
21903
|
-
const
|
|
21904
|
-
const touch =
|
|
21905
|
-
(event && event.changedTouches && event.changedTouches[0]) ||
|
|
21906
|
-
(event && event.touches && event.touches[0]);
|
|
21907
|
-
if (!touch) return null;
|
|
21908
|
-
const x = Number(touch.screenX ?? touch.clientX);
|
|
21909
|
-
const y = Number(touch.screenY ?? touch.clientY);
|
|
21910
|
-
return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
|
|
21911
|
-
};
|
|
21912
|
-
const handleScroll = (event) => {
|
|
22284
|
+
const handleScroll = event => {
|
|
21913
22285
|
const offsetY = Math.max(0, Number(event && event.top) || 0);
|
|
21914
22286
|
epubScrollDiagnostics && epubScrollDiagnostics.scroll(event);
|
|
21915
|
-
if (Math.abs(offsetY
|
|
21916
|
-
lastScrollOffset
|
|
21917
|
-
sendEvent('VIEWER_SCROLL',
|
|
21918
|
-
};
|
|
21919
|
-
const handleTouchStart = (event) => {
|
|
21920
|
-
touchStart = getTouchPoint(event);
|
|
21921
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchStart(event);
|
|
21922
|
-
};
|
|
21923
|
-
const handleTouchMove = (event) => {
|
|
21924
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchMove(event);
|
|
21925
|
-
};
|
|
21926
|
-
const handleTouchEnd = (event) => {
|
|
21927
|
-
const end = getTouchPoint(event);
|
|
21928
|
-
const start = touchStart;
|
|
21929
|
-
touchStart = null;
|
|
21930
|
-
const selectedText = event?.target?.ownerDocument?.defaultView?.getSelection?.()?.toString().trim() || '';
|
|
21931
|
-
if (!selectedText && start && end && Math.hypot(end.x - start.x, end.y - start.y) <= 12) {
|
|
21932
|
-
sendEvent('VIEWER_TAP', {});
|
|
21933
|
-
}
|
|
21934
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchEnd(event);
|
|
22287
|
+
if (Math.abs(offsetY-lastScrollOffset)<1) return;
|
|
22288
|
+
lastScrollOffset=offsetY;
|
|
22289
|
+
sendEvent('VIEWER_SCROLL',{offsetY});
|
|
21935
22290
|
};
|
|
21936
|
-
|
|
21937
22291
|
manager.on('scroll', handleScroll);
|
|
21938
22292
|
const handleScrolled = (event) => {
|
|
21939
22293
|
epubScrollDiagnostics && epubScrollDiagnostics.settled(event);
|
|
21940
22294
|
};
|
|
21941
22295
|
manager.on('scrolled', handleScrolled);
|
|
21942
|
-
|
|
21943
|
-
rendition.on('touchmove', handleTouchMove);
|
|
21944
|
-
rendition.on('touchend', handleTouchEnd);
|
|
22296
|
+
|
|
21945
22297
|
epubInteractionCleanup = () => {
|
|
21946
22298
|
epubSelectionCleanups.forEach((cleanup) => cleanup());
|
|
21947
22299
|
epubSelectionCleanups.clear();
|
|
@@ -21950,16 +22302,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21950
22302
|
if (originalEnqueue) queue.enqueue = originalEnqueue;
|
|
21951
22303
|
if (typeof manager.off === 'function') manager.off('scroll', handleScroll);
|
|
21952
22304
|
if (typeof manager.off === 'function') manager.off('scrolled', handleScrolled);
|
|
21953
|
-
if (typeof rendition.off === 'function') {
|
|
21954
|
-
rendition.off('touchstart', handleTouchStart);
|
|
21955
|
-
rendition.off('touchmove', handleTouchMove);
|
|
21956
|
-
rendition.off('touchend', handleTouchEnd);
|
|
21957
|
-
}
|
|
21958
22305
|
epubScrollDiagnostics = null;
|
|
21959
22306
|
};
|
|
21960
22307
|
}
|
|
21961
|
-
applyEpubZoom();
|
|
21962
|
-
|
|
21963
22308
|
const outline = await withEpubStageTimeout(
|
|
21964
22309
|
buildOutline(),
|
|
21965
22310
|
'outline',
|
|
@@ -21973,6 +22318,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21973
22318
|
return { pageCount, outline };
|
|
21974
22319
|
};
|
|
21975
22320
|
|
|
22321
|
+
let epubNavigationQueue = Promise.resolve();
|
|
22322
|
+
let epubNavigationRequest = 0;
|
|
21976
22323
|
const displayEpubPage = async (pageIndex) => {
|
|
21977
22324
|
if (!rendition) return;
|
|
21978
22325
|
const item = spineItems[pageIndex];
|
|
@@ -21982,9 +22329,19 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21982
22329
|
target,
|
|
21983
22330
|
pageIndex,
|
|
21984
22331
|
});
|
|
21985
|
-
|
|
21986
|
-
|
|
21987
|
-
|
|
22332
|
+
const activeRendition = rendition;
|
|
22333
|
+
const session = documentSessionId;
|
|
22334
|
+
const request = ++epubNavigationRequest;
|
|
22335
|
+
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22336
|
+
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22337
|
+
epubResizeAnchor?.invalidate();
|
|
22338
|
+
await activeRendition.display(target);
|
|
22339
|
+
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22340
|
+
currentPage = pageIndex + 1;
|
|
22341
|
+
sendState();
|
|
22342
|
+
});
|
|
22343
|
+
epubNavigationQueue = navigation;
|
|
22344
|
+
await navigation;
|
|
21988
22345
|
};
|
|
21989
22346
|
|
|
21990
22347
|
const getTextContent = async (pageIndex) => {
|
|
@@ -22086,6 +22443,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22086
22443
|
};
|
|
22087
22444
|
|
|
22088
22445
|
let nativeMenuSelection = null;
|
|
22446
|
+
let epubViewMode = "single";
|
|
22447
|
+
let epubLocation = null;
|
|
22089
22448
|
|
|
22090
22449
|
const handleCommand = async (message) => {
|
|
22091
22450
|
const { id, kind, payload } = message;
|
|
@@ -22097,7 +22456,13 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22097
22456
|
documentSessionId = payload.documentSessionId || null;
|
|
22098
22457
|
epubAnnotations = [];
|
|
22099
22458
|
annotationDocumentId = undefined;
|
|
22459
|
+
epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
22100
22460
|
zoom = 1.0;
|
|
22461
|
+
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22462
|
+
epubLocation = null;
|
|
22463
|
+
nativeMenuSelection = null;
|
|
22464
|
+
epubNavigationRequest += 1;
|
|
22465
|
+
epubNavigationQueue = Promise.resolve();
|
|
22101
22466
|
|
|
22102
22467
|
if (currentType === 'text') {
|
|
22103
22468
|
const result = await loadText(
|
|
@@ -22152,17 +22517,24 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22152
22517
|
epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22153
22518
|
} else {
|
|
22154
22519
|
const annotation = epubAnnotations.find(a => a.id === payload.annotationId);
|
|
22155
|
-
if (!annotation) throw new Error('Annotation not available');
|
|
22520
|
+
if (!annotation || (annotation.anchor.documentId && annotation.anchor.documentId !== annotationDocumentId)) throw new Error('Annotation not available for this document');
|
|
22156
22521
|
// Navigation uses the CFI, never a synthetic percentage/page rectangle.
|
|
22157
22522
|
const navigationSession = documentSessionId;
|
|
22158
22523
|
const activeRendition = rendition;
|
|
22159
22524
|
// Open the confirmed chapter first, resolve its quote, then navigate its actual range.
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22525
|
+
epubNavigationRequest += 1;
|
|
22526
|
+
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22527
|
+
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22528
|
+
epubResizeAnchor?.invalidate();
|
|
22529
|
+
await activeRendition.display(annotation.anchor.href);
|
|
22530
|
+
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22531
|
+
const contents = activeRendition.getContents().find(c => spineItems[c.sectionIndex]?.href === annotation.anchor.href);
|
|
22532
|
+
const range = contents && window.PapyrusEpubAnnotations.resolveRange(contents,annotation.anchor);
|
|
22533
|
+
if(!range)throw new Error('EPUB anchor unresolved');
|
|
22534
|
+
await activeRendition.display(contents.cfiFromRange(range));
|
|
22535
|
+
});
|
|
22536
|
+
epubNavigationQueue = navigation;
|
|
22537
|
+
await navigation;
|
|
22166
22538
|
}
|
|
22167
22539
|
sendResponse(id,true,null); return;
|
|
22168
22540
|
}
|
|
@@ -22189,12 +22561,61 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22189
22561
|
return;
|
|
22190
22562
|
}
|
|
22191
22563
|
|
|
22564
|
+
if (kind === 'epub-turn-page') {
|
|
22565
|
+
if (epubViewMode !== 'single') {sendResponse(id,true,null); return;}
|
|
22566
|
+
if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB navigation');
|
|
22567
|
+
const active = rendition;
|
|
22568
|
+
epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
|
|
22569
|
+
if (active !== rendition || payload.documentSessionId !== documentSessionId) return;
|
|
22570
|
+
epubResizeAnchor?.invalidate();
|
|
22571
|
+
return payload.direction < 0 ? active.prev() : active.next();
|
|
22572
|
+
});
|
|
22573
|
+
await epubNavigationQueue;
|
|
22574
|
+
sendResponse(id,true,null); return;
|
|
22575
|
+
}
|
|
22576
|
+
|
|
22577
|
+
if (kind === 'set-epub-view-mode') {
|
|
22578
|
+
if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB layout session');
|
|
22579
|
+
const next=payload.epubMode ? (payload.epubMode==='paged'?'single':'continuous') : (payload.viewMode==='single'?'single':'continuous');
|
|
22580
|
+
{
|
|
22581
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22582
|
+
if(payload.documentSessionId!==documentSessionId || next===epubViewMode)return;
|
|
22583
|
+
const target=epubResizeAnchor?.cfi() || epubLocation?.cfi;
|
|
22584
|
+
epubViewMode=next;
|
|
22585
|
+
await renderEpubRendition('layout',epubLoadGeneration,target);
|
|
22586
|
+
});
|
|
22587
|
+
await epubNavigationQueue;
|
|
22588
|
+
}
|
|
22589
|
+
sendResponse(id,true,null);return;
|
|
22590
|
+
}
|
|
22591
|
+
if (kind === 'set-epub-ink-mode') {
|
|
22592
|
+
if(currentType!=='epub'||!documentSessionId||payload.documentSessionId!==documentSessionId)throw new Error('Stale EPUB ink session');
|
|
22593
|
+
epubInkMode={enabled:payload.enabled===true,preset:['ink','highlight','underline'].indexOf(payload.preset)>=0?payload.preset:'ink',color:/^#[0-9a-f]{6}$/i.test(payload.color||'')?payload.color:'#2563eb',opacity:Number.isFinite(payload.opacity)?Math.max(0,Math.min(1,payload.opacity)):1,strokeWidth:Number.isFinite(payload.strokeWidth)?Math.max(0.0025,Math.min(0.02,payload.strokeWidth)):0.006};
|
|
22594
|
+
epubAnnotationRenderers.forEach(renderer=>renderer.setInkMode(epubInkMode));
|
|
22595
|
+
sendResponse(id,true,null);return;
|
|
22596
|
+
}
|
|
22597
|
+
if(kind === 'epub-go-to-location'){
|
|
22598
|
+
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22599
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>{if(payload.documentSessionId!==documentSessionId)return;epubResizeAnchor?.invalidate();return rendition.display(payload.cfi);});
|
|
22600
|
+
await epubNavigationQueue;sendResponse(id,true,null);return;
|
|
22601
|
+
}
|
|
22602
|
+
|
|
22192
22603
|
if (kind === 'set-zoom') {
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22197
|
-
|
|
22604
|
+
const requestedZoom=Math.max(0.5,Math.min(4.0,payload.zoom || 1.0));
|
|
22605
|
+
if(currentType === 'epub') {
|
|
22606
|
+
const session=documentSessionId;
|
|
22607
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22608
|
+
if(session!==documentSessionId)return;
|
|
22609
|
+
const active=rendition;
|
|
22610
|
+
const cfi=epubResizeAnchor?.cfi() || epubLocation?.cfi;
|
|
22611
|
+
zoom=requestedZoom;applyEpubZoom();
|
|
22612
|
+
// Let the content CSS update before redisplaying the logical anchor.
|
|
22613
|
+
await new Promise(resolve=>(window.requestAnimationFrame || (callback=>setTimeout(callback,0)))(resolve));
|
|
22614
|
+
if(cfi && active===rendition && session===documentSessionId)await active.display(cfi);
|
|
22615
|
+
});
|
|
22616
|
+
await epubNavigationQueue;
|
|
22617
|
+
} else {zoom=requestedZoom;applyZoom();}
|
|
22618
|
+
sendState();sendResponse(id,true,{zoom});return;
|
|
22198
22619
|
}
|
|
22199
22620
|
|
|
22200
22621
|
if (kind === 'set-rotation') {
|