@papyrus-sdk/ui-react-native 0.2.35 → 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.js +313 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +314 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -8
- package/runtime/epubAnnotations.js +271 -6
- package/runtime/epubReader.js +1 -1
- package/runtime/index.html +284 -8
- package/runtime/runtime.js +284 -8
- package/runtime/comicRuntime.test.ts +0 -241
- package/runtime/documentLoadRuntime.test.ts +0 -172
- package/runtime/epubAnnotations.test.ts +0 -35
- package/runtime/epubReader.test.ts +0 -74
- package/runtime/epubRuntime.test.ts +0 -48
- package/runtime/epubScrollDiagnostics.test.ts +0 -107
- package/runtime/epubSelectionMenu.test.ts +0 -39
package/dist/index.js
CHANGED
|
@@ -20564,7 +20564,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20564
20564
|
var doc=contents.document,win=contents.window,start=null,blocked=false;
|
|
20565
20565
|
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;}
|
|
20566
20566
|
function selected(){return Boolean(String(win.getSelection()||'').trim()) || config.blocked();}
|
|
20567
|
-
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay]'));}
|
|
20567
|
+
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay],[data-papyrus-ink-capture]'));}
|
|
20568
20568
|
function begin(e){start=point(e);blocked=e.touches.length!==1 || selected() || interactive(e.target);}
|
|
20569
20569
|
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();}
|
|
20570
20570
|
function move(e){if(e.touches.length!==1)blocked=true;invalidateScroll(point(e));}
|
|
@@ -20589,6 +20589,84 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20589
20589
|
typeof anchor.href === 'string' && !/^(javascript|data):/i.test(anchor.href) &&
|
|
20590
20590
|
typeof anchor.quote === 'string' && anchor.quote.length > 0 && anchor.quote.length <= 100000;
|
|
20591
20591
|
}
|
|
20592
|
+
function simplifyPath(points, tolerance, maxPoints) {
|
|
20593
|
+
if (!Array.isArray(points) || points.length <= 2) return Array.isArray(points) ? points.slice() : [];
|
|
20594
|
+
tolerance = Number.isFinite(tolerance) ? Math.max(0, tolerance) : 1.5;
|
|
20595
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20596
|
+
var keep = new Uint8Array(points.length); keep[0] = 1; keep[points.length - 1] = 1;
|
|
20597
|
+
var stack = [[0, points.length - 1]], toleranceSquared = tolerance * tolerance;
|
|
20598
|
+
while (stack.length) {
|
|
20599
|
+
var interval = stack.pop(), first = interval[0], last = interval[1], a = points[first], b = points[last];
|
|
20600
|
+
var dx = b.x - a.x, dy = b.y - a.y, lengthSquared = dx * dx + dy * dy, maxDistance = toleranceSquared, split = -1;
|
|
20601
|
+
for (var i = first + 1; i < last; i++) {
|
|
20602
|
+
var p = points[i], ratio = lengthSquared ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared)) : 0;
|
|
20603
|
+
var px = a.x + ratio * dx, py = a.y + ratio * dy, ox = p.x - px, oy = p.y - py, distance = ox * ox + oy * oy;
|
|
20604
|
+
if (distance > maxDistance) { maxDistance = distance; split = i; }
|
|
20605
|
+
}
|
|
20606
|
+
if (split >= 0) { keep[split] = 1; stack.push([first, split], [split, last]); }
|
|
20607
|
+
}
|
|
20608
|
+
var result = []; for (var j = 0; j < points.length; j++) if (keep[j]) result.push(points[j]);
|
|
20609
|
+
if (result.length <= maxPoints) return result;
|
|
20610
|
+
var capped = []; for (var k = 0; k < maxPoints; k++) capped.push(result[Math.round(k * (result.length - 1) / (maxPoints - 1))]);
|
|
20611
|
+
return capped;
|
|
20612
|
+
}
|
|
20613
|
+
function compactGesturePoints(points, maxPoints) {
|
|
20614
|
+
if (!Array.isArray(points)) return [];
|
|
20615
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 1024;
|
|
20616
|
+
if (points.length <= maxPoints) return points.slice();
|
|
20617
|
+
var compacted = [];
|
|
20618
|
+
for (var i = 0; i < maxPoints; i++) compacted.push(points[Math.round(i * (points.length - 1) / (maxPoints - 1))]);
|
|
20619
|
+
return compacted;
|
|
20620
|
+
}
|
|
20621
|
+
function densifyPath(points, maxStep, maxPoints) {
|
|
20622
|
+
if (!Array.isArray(points) || !points.length) return [];
|
|
20623
|
+
if (points.length === 1) return points.slice();
|
|
20624
|
+
maxStep = Number.isFinite(maxStep) ? Math.max(1, maxStep) : 12;
|
|
20625
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20626
|
+
var cumulative = [0], total = 0;
|
|
20627
|
+
for (var i = 1; i < points.length; i++) {
|
|
20628
|
+
if (![points[i-1].x,points[i-1].y,points[i].x,points[i].y].every(Number.isFinite)) return [];
|
|
20629
|
+
total += Math.hypot(points[i].x-points[i-1].x, points[i].y-points[i-1].y);
|
|
20630
|
+
cumulative.push(total);
|
|
20631
|
+
}
|
|
20632
|
+
if (!total) return [points[0], points[points.length-1]];
|
|
20633
|
+
var intervals = Math.min(maxPoints-1, Math.max(1, Math.ceil(total/maxStep))), result = [], segment = 1;
|
|
20634
|
+
for (var sample = 0; sample <= intervals; sample++) {
|
|
20635
|
+
var distance = total*sample/intervals;
|
|
20636
|
+
while (segment < cumulative.length-1 && cumulative[segment] < distance) segment++;
|
|
20637
|
+
var start = points[segment-1], end = points[segment], span = cumulative[segment]-cumulative[segment-1];
|
|
20638
|
+
var ratio = span ? (distance-cumulative[segment-1])/span : 0;
|
|
20639
|
+
result.push({x:start.x+(end.x-start.x)*ratio,y:start.y+(end.y-start.y)*ratio});
|
|
20640
|
+
}
|
|
20641
|
+
return result;
|
|
20642
|
+
}
|
|
20643
|
+
function createSpatialIndex(entries, cellSize) {
|
|
20644
|
+
cellSize = Number.isFinite(cellSize) ? Math.max(8, cellSize) : 64;
|
|
20645
|
+
var cells = new Map();
|
|
20646
|
+
entries.forEach(function(entry) {
|
|
20647
|
+
var left = Math.floor(entry.left / cellSize), right = Math.floor(entry.right / cellSize);
|
|
20648
|
+
var top = Math.floor(entry.top / cellSize), bottom = Math.floor(entry.bottom / cellSize);
|
|
20649
|
+
for (var x = left; x <= right; x++) for (var y = top; y <= bottom; y++) {
|
|
20650
|
+
var key = x + ':' + y, bucket = cells.get(key); if (!bucket) { bucket = []; cells.set(key, bucket); } bucket.push(entry);
|
|
20651
|
+
}
|
|
20652
|
+
});
|
|
20653
|
+
return {cells:cells,cellSize:cellSize};
|
|
20654
|
+
}
|
|
20655
|
+
function queryNearestTextRect(index, x, y, maxDistance) {
|
|
20656
|
+
if (!index || !Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(maxDistance) || maxDistance < 0) return null;
|
|
20657
|
+
var size = index.cellSize, minX = Math.floor((x-maxDistance)/size), maxX = Math.floor((x+maxDistance)/size);
|
|
20658
|
+
var minY = Math.floor((y-maxDistance)/size), maxY = Math.floor((y+maxDistance)/size), seen = new Set(), best = null;
|
|
20659
|
+
for (var cx=minX; cx<=maxX; cx++) for (var cy=minY; cy<=maxY; cy++) {
|
|
20660
|
+
var bucket = index.cells.get(cx+':'+cy); if (!bucket) continue;
|
|
20661
|
+
bucket.forEach(function(entry) {
|
|
20662
|
+
if (seen.has(entry)) return; seen.add(entry);
|
|
20663
|
+
var nearestX = Math.max(entry.left,Math.min(entry.right,x)), nearestY = Math.max(entry.top,Math.min(entry.bottom,y));
|
|
20664
|
+
var dx=x-nearestX,dy=y-nearestY,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20665
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={entry:entry,distance:distance,x:nearestX,y:nearestY};
|
|
20666
|
+
});
|
|
20667
|
+
}
|
|
20668
|
+
return best;
|
|
20669
|
+
}
|
|
20592
20670
|
function textNodes(document) {
|
|
20593
20671
|
var walker = document.createTreeWalker(document.body, 4);
|
|
20594
20672
|
var nodes = [], text = '', node;
|
|
@@ -20638,13 +20716,196 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20638
20716
|
if(win.getComputedStyle(doc.body).position==='static')doc.body.style.position='relative';
|
|
20639
20717
|
doc.body.appendChild(overlay);
|
|
20640
20718
|
var registry = new Map(), hitRegions = [];
|
|
20719
|
+
var inkRegistry = new Map(), rangeCache = new Map(), spatialIndex = null, activeGesture = null, inkConfig = {enabled:false,preset:'ink'};
|
|
20720
|
+
var inkSvg = doc.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
20721
|
+
inkSvg.setAttribute('data-papyrus-ink-overlay','');
|
|
20722
|
+
inkSvg.style.cssText = 'position:absolute;left:0;top:0;overflow:visible;pointer-events:none;z-index:1';
|
|
20723
|
+
overlay.appendChild(inkSvg);
|
|
20724
|
+
var inkCanvas = doc.createElement('canvas');
|
|
20725
|
+
inkCanvas.dataset.papyrusInkCapture = '';
|
|
20726
|
+
inkCanvas.style.cssText = 'position:fixed;left:0;top:0;width:1px;height:1px;z-index:2147483000;background:transparent;pointer-events:none;touch-action:none';
|
|
20727
|
+
doc.body.appendChild(inkCanvas);
|
|
20728
|
+
var inkContext = null; try { if(typeof win.CanvasRenderingContext2D==='function')inkContext = inkCanvas.getContext('2d'); } catch (_) {}
|
|
20729
|
+
function resizeCanvas() {
|
|
20730
|
+
var bodyRect=doc.body.getBoundingClientRect(), ratio = Math.max(1,Math.min(3,win.devicePixelRatio || 1));
|
|
20731
|
+
var width=Math.max(1,Math.min(4096,doc.body.clientWidth||bodyRect.width||Math.min(4096,win.innerWidth||1)));
|
|
20732
|
+
var height=Math.max(1,Math.min(4096,doc.body.clientHeight||bodyRect.height||Math.min(4096,win.innerHeight||1)));
|
|
20733
|
+
inkCanvas.style.width=width+'px';inkCanvas.style.height=height+'px';
|
|
20734
|
+
inkCanvas.width = Math.round(width*ratio); inkCanvas.height = Math.round(height*ratio);
|
|
20735
|
+
if (inkContext) { inkContext.setTransform(ratio,0,0,ratio,0,0); inkContext.clearRect(0,0,width,height); }
|
|
20736
|
+
}
|
|
20737
|
+
function collectTextRects() {
|
|
20738
|
+
var walker = doc.createTreeWalker(doc.body,4), node, entries=[];
|
|
20739
|
+
while ((node=walker.nextNode())) {
|
|
20740
|
+
var parent=node.parentElement;
|
|
20741
|
+
if (!parent || parent.closest('script,style,noscript,textarea,[data-papyrus-overlay],[data-papyrus-ink-capture]')) continue;
|
|
20742
|
+
var text=node.nodeValue || '', style=win.getComputedStyle(parent), computed=parseFloat(style.lineHeight);
|
|
20743
|
+
for (var start=0; start<text.length;) {
|
|
20744
|
+
var end=Math.min(text.length,start+24), last=text.charCodeAt(end-1), next=text.charCodeAt(end);
|
|
20745
|
+
if(end<text.length&&last>=0xD800&&last<=0xDBFF&&next>=0xDC00&&next<=0xDFFF)end++;
|
|
20746
|
+
var range=doc.createRange(); range.setStart(node,start); range.setEnd(node,end);
|
|
20747
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20748
|
+
rects.forEach(function(rect) {
|
|
20749
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20750
|
+
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,
|
|
20751
|
+
node:node,start:start,end:end,lineHeight:Number.isFinite(computed)&&computed>0?computed:rect.height});
|
|
20752
|
+
});
|
|
20753
|
+
start=end;
|
|
20754
|
+
}
|
|
20755
|
+
}
|
|
20756
|
+
return entries;
|
|
20757
|
+
}
|
|
20758
|
+
function rebuildSpatialIndex() { spatialIndex=createSpatialIndex(collectTextRects(),64); rangeCache.clear(); }
|
|
20759
|
+
function inkViewportExtent() {
|
|
20760
|
+
var root=doc.documentElement,body=doc.body,bodyRect=body.getBoundingClientRect();
|
|
20761
|
+
var width=root.clientWidth||body.clientWidth||bodyRect.width||win.innerWidth||1;
|
|
20762
|
+
var height=root.clientHeight||body.clientHeight||bodyRect.height||win.innerHeight||1;
|
|
20763
|
+
return Math.max(1,Math.min(4096,width),Math.min(4096,height));
|
|
20764
|
+
}
|
|
20765
|
+
function inkStrokeWidthPx(width,preset) {
|
|
20766
|
+
var scale=preset==='highlight'?0.8:preset==='underline'?0.1:0.15;
|
|
20767
|
+
return Math.max(1,Math.min(24,(Number.isFinite(width)?width:0.006)*inkViewportExtent()*scale));
|
|
20768
|
+
}
|
|
20769
|
+
function closestGlyph(entry,x,y,maxDistance) {
|
|
20770
|
+
var source=(entry.node.nodeValue || '').slice(entry.start,entry.end), best=null, offset=0;
|
|
20771
|
+
for (var glyph of source) {
|
|
20772
|
+
var range=doc.createRange(); range.setStart(entry.node,entry.start+offset); range.setEnd(entry.node,entry.start+offset+glyph.length); offset+=glyph.length;
|
|
20773
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20774
|
+
rects.forEach(function(rect) {
|
|
20775
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20776
|
+
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));
|
|
20777
|
+
var dx=x-nx,dy=y-ny,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20778
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={range:range,rect:rect,distance:distance};
|
|
20779
|
+
});
|
|
20780
|
+
}
|
|
20781
|
+
if (!best || typeof contents.cfiFromRange!=='function') return null;
|
|
20782
|
+
var quote=best.range.toString(), cfiRange; try { cfiRange=contents.cfiFromRange(best.range); } catch (_) { return null; }
|
|
20783
|
+
if (!quote || typeof cfiRange!=='string' || !/^epubcfi\\([^\\n<>]+\\)$/.test(cfiRange)) return null;
|
|
20784
|
+
var lineHeight=Math.max(1,entry.lineHeight || best.rect.height), px=x-(best.rect.left+win.scrollX), py=y-(best.rect.top+win.scrollY);
|
|
20785
|
+
return {cfiRange:cfiRange,quote:quote,x:Math.max(-3,Math.min(3,px/lineHeight)),y:Math.max(-3,Math.min(3,py/lineHeight))};
|
|
20786
|
+
}
|
|
20787
|
+
function renderInkAnnotation(annotation,keep,bodyRect) {
|
|
20788
|
+
var baseRect=bodyRect || doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20789
|
+
var data=annotation.epubInk;
|
|
20790
|
+
if (!data || data.version!==1 || data.kind!=='epub-ink' || !Array.isArray(data.segments)) return;
|
|
20791
|
+
keep.add(annotation.id);
|
|
20792
|
+
var group=inkRegistry.get(annotation.id);
|
|
20793
|
+
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); }
|
|
20794
|
+
group.replaceChildren();
|
|
20795
|
+
var color=/^#[0-9a-f]{6}$/i.test(annotation.color)?annotation.color:'#2563eb';
|
|
20796
|
+
var opacity=Number.isFinite(annotation.opacity)?Math.max(0,Math.min(1,annotation.opacity)):1;
|
|
20797
|
+
var preset=['ink','highlight','underline'].indexOf(data.preset)>=0?data.preset:'ink';
|
|
20798
|
+
var stroke=inkStrokeWidthPx(annotation.strokeWidth,preset);
|
|
20799
|
+
data.segments.forEach(function(segment) {
|
|
20800
|
+
if (segment.href!==options.href || !Array.isArray(segment.points)) return;
|
|
20801
|
+
var paths=[], current=[];
|
|
20802
|
+
segment.points.forEach(function(point) {
|
|
20803
|
+
var range=rangeCache.get(point.cfiRange);
|
|
20804
|
+
if (!range) { try { range=contents.range(point.cfiRange); } catch (_) { range=null; } if (range) rangeCache.set(point.cfiRange,range); }
|
|
20805
|
+
if (!range || range.toString()!==point.quote) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20806
|
+
var rect; try { rect=range.getBoundingClientRect(); } catch (_) { rect=null; }
|
|
20807
|
+
if (!rect || !(rect.width>0 && rect.height>0)) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20808
|
+
var lineHeight=Math.max(1,rect.height), x=rect.left-baseRect.left+point.x*lineHeight, y=rect.top-baseRect.top+point.y*lineHeight;
|
|
20809
|
+
var previous=current[current.length-1], jumpLimit=Math.max(24,lineHeight*2.5);
|
|
20810
|
+
if (previous && Math.hypot(x-previous.x,y-previous.y)>jumpLimit) { if(current.length>1)paths.push(current);current=[]; }
|
|
20811
|
+
current.push({x:x,y:y,lineHeight:lineHeight});
|
|
20812
|
+
});
|
|
20813
|
+
if(current.length>1)paths.push(current);
|
|
20814
|
+
paths.forEach(function(points) {
|
|
20815
|
+
var d='M '+points[0].x.toFixed(1)+' '+points[0].y.toFixed(1);
|
|
20816
|
+
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);}
|
|
20817
|
+
var last=points[points.length-1];d+=' L '+last.x.toFixed(1)+' '+last.y.toFixed(1);
|
|
20818
|
+
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);
|
|
20819
|
+
});
|
|
20820
|
+
});
|
|
20821
|
+
}
|
|
20822
|
+
function clearPreview() {
|
|
20823
|
+
if(inkContext)inkContext.clearRect(0,0,inkCanvas.width,inkCanvas.height);
|
|
20824
|
+
inkSvg.querySelectorAll('[data-papyrus-ink-preview]').forEach(function(path){path.remove();});
|
|
20825
|
+
}
|
|
20826
|
+
function createPreviewPath(x,y) {
|
|
20827
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');
|
|
20828
|
+
path.setAttribute('data-papyrus-ink-preview','');path.setAttribute('d','M '+x.toFixed(1)+' '+y.toFixed(1));path.setAttribute('fill','none');
|
|
20829
|
+
path.setAttribute('stroke',inkConfig.color);path.setAttribute('stroke-width',String(inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset)));
|
|
20830
|
+
path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(inkConfig.opacity));
|
|
20831
|
+
path.style.pointerEvents='none';inkSvg.appendChild(path);return path;
|
|
20832
|
+
}
|
|
20833
|
+
function updatePreviewPath(clientX,clientY) {
|
|
20834
|
+
var bodyRect=doc.body.getBoundingClientRect(),x=clientX-bodyRect.left,y=clientY-bodyRect.top;
|
|
20835
|
+
var gesture=activeGesture;
|
|
20836
|
+
if(!gesture.previewPath||gesture.previewPathPoints>=32){
|
|
20837
|
+
gesture.previewPath=createPreviewPath(gesture.previewLast?gesture.previewLast.x:x,gesture.previewLast?gesture.previewLast.y:y);
|
|
20838
|
+
gesture.previewPathPoints=1;
|
|
20839
|
+
}
|
|
20840
|
+
var pathData=gesture.previewPath.getAttribute('d')||'';
|
|
20841
|
+
gesture.previewPath.setAttribute('d',pathData+' L '+x.toFixed(1)+' '+y.toFixed(1));
|
|
20842
|
+
gesture.previewPathPoints++;
|
|
20843
|
+
gesture.previewLast={x:x,y:y};
|
|
20844
|
+
}
|
|
20845
|
+
function cancelGesture() {
|
|
20846
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20847
|
+
if(gesture)try{inkCanvas.releasePointerCapture(gesture.pointerId);}catch(_){}
|
|
20848
|
+
}
|
|
20849
|
+
function commitGesture() {
|
|
20850
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20851
|
+
if(!gesture || !alive || !options.isCurrent() || !inkConfig.enabled || !spatialIndex) return;
|
|
20852
|
+
var simplified=simplifyPath(gesture.points,1.5,512), anchorSamples=densifyPath(simplified,12,512), segments=[], current=[];
|
|
20853
|
+
anchorSamples.forEach(function(point) {
|
|
20854
|
+
var coarse=queryNearestTextRect(spatialIndex,point.x,point.y,28);
|
|
20855
|
+
var cutoff=coarse?Math.max(12,Math.min(28,0.8*coarse.entry.lineHeight)):12;
|
|
20856
|
+
var anchored=coarse && closestGlyph(coarse.entry,point.x,point.y,cutoff);
|
|
20857
|
+
if(!anchored){if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});current=[];return;}
|
|
20858
|
+
current.push(anchored);
|
|
20859
|
+
});
|
|
20860
|
+
if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});
|
|
20861
|
+
segments=segments.slice(0,64);
|
|
20862
|
+
var pointCount=segments.reduce(function(total,segment){return total+segment.points.length;},0);
|
|
20863
|
+
if(!pointCount)return;
|
|
20864
|
+
var width=Math.max(1,doc.documentElement.scrollWidth,win.innerWidth),height=Math.max(1,doc.documentElement.scrollHeight,win.innerHeight);
|
|
20865
|
+
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))};});
|
|
20866
|
+
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;}));
|
|
20867
|
+
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;}));
|
|
20868
|
+
var first=segments[0].points[0], href=segments[0].href, documentId=typeof options.documentId==='function'?options.documentId():options.documentId;
|
|
20869
|
+
var annotation={id:'epub-ink-'+Date.now()+'-'+Math.random().toString(36).slice(2,9),type:'ink',pageIndex:(options.spineIndex||0)+1,
|
|
20870
|
+
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,
|
|
20871
|
+
anchor:{version:1,kind:'epub-cfi',cfiRange:first.cfiRange,href:href,spineIndex:options.spineIndex,documentId:documentId,quote:first.quote},
|
|
20872
|
+
epubInk:{version:1,kind:'epub-ink',documentId:documentId,preset:inkConfig.preset,segments:segments}};
|
|
20873
|
+
if(typeof options.onInkCommit==='function')options.onInkCommit(annotation);
|
|
20874
|
+
}
|
|
20875
|
+
function pointerDown(event) {
|
|
20876
|
+
if(!inkConfig.enabled || !alive || !options.isCurrent() || event.button!==undefined && event.button!==0)return;
|
|
20877
|
+
if(activeGesture){cancelGesture();return;}
|
|
20878
|
+
event.preventDefault();event.stopPropagation();
|
|
20879
|
+
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};
|
|
20880
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20881
|
+
try{inkCanvas.setPointerCapture(event.pointerId);}catch(_){}
|
|
20882
|
+
}
|
|
20883
|
+
function pointerMove(event) {
|
|
20884
|
+
if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;
|
|
20885
|
+
if(!options.isCurrent()||!inkConfig.enabled){cancelGesture();return;}
|
|
20886
|
+
event.preventDefault();event.stopPropagation();
|
|
20887
|
+
var point={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY};activeGesture.points.push(point);
|
|
20888
|
+
if(activeGesture.points.length>2048)activeGesture.points=compactGesturePoints(activeGesture.points,1024);
|
|
20889
|
+
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();}
|
|
20890
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20891
|
+
activeGesture.last={x:event.clientX,y:event.clientY};
|
|
20892
|
+
}
|
|
20893
|
+
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();}
|
|
20894
|
+
function pointerCancel(event) {if(activeGesture && (event.pointerId===undefined || activeGesture.pointerId===event.pointerId))cancelGesture();}
|
|
20895
|
+
resizeCanvas();rebuildSpatialIndex();
|
|
20896
|
+
inkCanvas.addEventListener('pointerdown',pointerDown);inkCanvas.addEventListener('pointermove',pointerMove);inkCanvas.addEventListener('pointerup',pointerUp);inkCanvas.addEventListener('pointercancel',pointerCancel);inkCanvas.addEventListener('lostpointercapture',pointerCancel);
|
|
20897
|
+
win.addEventListener('blur',pointerCancel);win.addEventListener('resize',resizeCanvas);
|
|
20641
20898
|
function render() {
|
|
20642
20899
|
frame = 0; if (!alive || !options.isCurrent()) return;
|
|
20643
|
-
var keep = new Set(), noteGroups = new Map();
|
|
20900
|
+
var keep = new Set(), keepInk = new Set(), noteGroups = new Map();
|
|
20644
20901
|
hitRegions = [];
|
|
20902
|
+
var bodyRect=doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20903
|
+
inkSvg.setAttribute('width',String(Math.max(doc.documentElement.scrollWidth,win.innerWidth)));
|
|
20904
|
+
inkSvg.setAttribute('height',String(Math.max(doc.documentElement.scrollHeight,win.innerHeight)));
|
|
20645
20905
|
options.annotations().forEach(function(annotation) {
|
|
20646
20906
|
var anchor = annotation.anchor;
|
|
20647
20907
|
if (!validAnchor(anchor) || anchor.href !== options.href || anchor.documentId && options.documentId && anchor.documentId !== options.documentId) return;
|
|
20908
|
+
if(annotation.type==='ink' && annotation.epubInk){renderInkAnnotation(annotation,keepInk,bodyRect);return;}
|
|
20648
20909
|
var range = resolveRange(contents,anchor); if (!range) return;
|
|
20649
20910
|
var rects = Array.from(range.getClientRects()).filter(function(r){return r.width>0 && r.height>0;});
|
|
20650
20911
|
if (!rects.length) return;
|
|
@@ -20683,22 +20944,26 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20683
20944
|
group.button.addEventListener('click',function(e){e.stopPropagation();if(options.isCurrent())options.onTap(group.ids[0],group.ids);});
|
|
20684
20945
|
});
|
|
20685
20946
|
registry.forEach(function(group,id){if (!keep.has(id)) {group.remove();registry.delete(id);}});
|
|
20947
|
+
inkRegistry.forEach(function(group,id){if (!keepInk.has(id)) {group.remove();inkRegistry.delete(id);}});
|
|
20686
20948
|
}
|
|
20687
20949
|
function schedule() { if (alive && !frame) frame = win.requestAnimationFrame(render); }
|
|
20950
|
+
function rebuildAndSchedule(){if(!alive)return;rebuildSpatialIndex();schedule();}
|
|
20951
|
+
function handleResize(){resizeCanvas();rebuildAndSchedule();}
|
|
20952
|
+
function handleDocumentLoad(){rebuildAndSchedule();}
|
|
20688
20953
|
function tapMarkup(event) {
|
|
20689
20954
|
if(!alive || !options.isCurrent() || String(win.getSelection() || '').length || event.target.closest('[data-papyrus-overlay]'))return;
|
|
20690
20955
|
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;});});
|
|
20691
20956
|
if(hit) {event.stopPropagation();options.onTap(hit.id);}
|
|
20692
20957
|
}
|
|
20693
20958
|
doc.addEventListener('click',tapMarkup);
|
|
20694
|
-
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(
|
|
20959
|
+
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(rebuildAndSchedule) : null;
|
|
20695
20960
|
if (observer) observer.observe(doc.body);
|
|
20696
|
-
win.addEventListener('resize',
|
|
20697
|
-
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20961
|
+
win.addEventListener('resize',handleResize);win.addEventListener('scroll',schedule); doc.addEventListener('load',handleDocumentLoad,true);
|
|
20962
|
+
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(function(){if(alive){rebuildSpatialIndex();schedule();}});
|
|
20698
20963
|
schedule();
|
|
20699
|
-
return {schedule:schedule, 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;if(frame)win.cancelAnimationFrame(frame);if(observer)observer.disconnect();win.removeEventListener('resize',
|
|
20964
|
+
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();}};
|
|
20700
20965
|
}
|
|
20701
|
-
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20966
|
+
return {validAnchor:validAnchor,simplifyPath:simplifyPath,compactGesturePoints:compactGesturePoints,densifyPath:densifyPath,createSpatialIndex:createSpatialIndex,queryNearestTextRect:queryNearestTextRect,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20702
20967
|
});
|
|
20703
20968
|
|
|
20704
20969
|
/* @papyrus-epub-annotations:end */
|
|
@@ -20714,6 +20979,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20714
20979
|
let annotationDocumentId;
|
|
20715
20980
|
let annotationLabels = {};
|
|
20716
20981
|
let epubAnnotations = [];
|
|
20982
|
+
let epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
20717
20983
|
const epubAnnotationRenderers = new Map();
|
|
20718
20984
|
let spineItems = [];
|
|
20719
20985
|
let textPages = [];
|
|
@@ -21828,11 +22094,14 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21828
22094
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21829
22095
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21830
22096
|
href, get documentId() { return annotationDocumentId; },
|
|
22097
|
+
spineIndex:contents.sectionIndex,
|
|
21831
22098
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
21832
22099
|
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21833
22100
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
22101
|
+
onInkCommit: annotation => sendEvent('EPUB_INK_CREATED',{documentSessionId:session,annotation}),
|
|
21834
22102
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21835
22103
|
});
|
|
22104
|
+
renderer.setInkMode(epubInkMode);
|
|
21836
22105
|
epubAnnotationRenderers.set(contents,renderer);
|
|
21837
22106
|
}
|
|
21838
22107
|
const frame = contents && contents.document ? contents.document.defaultView.frameElement : null;
|
|
@@ -21924,7 +22193,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21924
22193
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21925
22194
|
});
|
|
21926
22195
|
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
21927
|
-
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22196
|
+
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => name==='relocated'?renderer.schedule():renderer.invalidateLayout());
|
|
21928
22197
|
}));
|
|
21929
22198
|
rendition.on('relocated', (location) => {
|
|
21930
22199
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
@@ -22221,6 +22490,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22221
22490
|
documentSessionId = payload.documentSessionId || null;
|
|
22222
22491
|
epubAnnotations = [];
|
|
22223
22492
|
annotationDocumentId = undefined;
|
|
22493
|
+
epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
22224
22494
|
zoom = 1.0;
|
|
22225
22495
|
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22226
22496
|
epubLocation = null;
|
|
@@ -22352,6 +22622,12 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22352
22622
|
}
|
|
22353
22623
|
sendResponse(id,true,null);return;
|
|
22354
22624
|
}
|
|
22625
|
+
if (kind === 'set-epub-ink-mode') {
|
|
22626
|
+
if(currentType!=='epub'||!documentSessionId||payload.documentSessionId!==documentSessionId)throw new Error('Stale EPUB ink session');
|
|
22627
|
+
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};
|
|
22628
|
+
epubAnnotationRenderers.forEach(renderer=>renderer.setInkMode(epubInkMode));
|
|
22629
|
+
sendResponse(id,true,null);return;
|
|
22630
|
+
}
|
|
22355
22631
|
if(kind === 'epub-go-to-location'){
|
|
22356
22632
|
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22357
22633
|
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>{if(payload.documentSessionId!==documentSessionId)return;epubResizeAnchor?.invalidate();return rendition.display(payload.cfi);});
|
|
@@ -26144,8 +26420,14 @@ var parseWebViewInteraction = (raw) => {
|
|
|
26144
26420
|
|
|
26145
26421
|
// components/epubAnnotationEvents.ts
|
|
26146
26422
|
var import_core3 = require("@papyrus-sdk/core");
|
|
26423
|
+
var EPUB_INK_PRESETS = ["ink", "highlight", "underline"];
|
|
26424
|
+
function resolveEpubInkMode(input) {
|
|
26425
|
+
if (!input.isLoaded || input.documentType !== "epub") return null;
|
|
26426
|
+
const preset = EPUB_INK_PRESETS.includes(input.preset) ? input.preset : "ink";
|
|
26427
|
+
return { enabled: input.activeTool === "ink" && EPUB_INK_PRESETS.includes(input.preset), preset, color: input.color, opacity: input.opacity, strokeWidth: input.strokeWidth };
|
|
26428
|
+
}
|
|
26147
26429
|
function parseEpubAnnotationEvent(raw, session, documentId) {
|
|
26148
|
-
if (!session || raw.length >
|
|
26430
|
+
if (!session || raw.length > 75e4) return null;
|
|
26149
26431
|
let message;
|
|
26150
26432
|
try {
|
|
26151
26433
|
message = JSON.parse(raw);
|
|
@@ -26155,6 +26437,13 @@ function parseEpubAnnotationEvent(raw, session, documentId) {
|
|
|
26155
26437
|
const p = message?.payload;
|
|
26156
26438
|
if (message?.type !== "event" || !p || p.documentSessionId !== session) return null;
|
|
26157
26439
|
if (message.name === "EPUB_ANNOTATION_TAP") return typeof p.id === "string" && p.id.length <= 256 ? { kind: "tap", id: p.id, ids: Array.isArray(p.ids) && p.ids.length <= 100 && p.ids.every((id) => typeof id === "string" && id.length <= 256) ? p.ids : void 0 } : null;
|
|
26440
|
+
if (message.name === "EPUB_INK_CREATED") {
|
|
26441
|
+
const a = p.annotation, sidecar = a?.epubInk, first = sidecar?.segments?.[0], point = first?.points?.[0];
|
|
26442
|
+
if (!a || a.type !== "ink" || typeof a.id !== "string" || !a.id || a.id.length > 256 || !Number.isSafeInteger(a.pageIndex) || a.pageIndex < 1 || !(0, import_core3.validateAnnotationAnchor)(a.anchor) || a.anchor.kind !== "epub-cfi" || !(0, import_core3.validateEpubInkData)(sidecar) || !point || a.anchor.cfiRange !== point.cfiRange || a.anchor.quote !== point.quote || a.anchor.href !== first.href || documentId && (sidecar.documentId && sidecar.documentId !== documentId || a.anchor.documentId && a.anchor.documentId !== documentId) || sidecar.documentId && a.anchor.documentId && sidecar.documentId !== a.anchor.documentId) return null;
|
|
26443
|
+
const rect = a.rect, path = a.path;
|
|
26444
|
+
if (!rect || ![rect.x, rect.y, rect.width, rect.height].every((n) => typeof n === "number" && Number.isFinite(n) && n >= 0 && n <= 1) || rect.x + rect.width > 1.000001 || rect.y + rect.height > 1.000001 || !Array.isArray(path) || path.length < 2 || path.length > 512 || path.some((p2) => !p2 || ![p2.x, p2.y].every((n) => typeof n === "number" && Number.isFinite(n) && n >= 0 && n <= 1)) || typeof a.color !== "string" || !/^#[0-9a-f]{6}$/i.test(a.color) || !Number.isFinite(a.createdAt) || a.opacity !== void 0 && (!Number.isFinite(a.opacity) || a.opacity < 0 || a.opacity > 1) || a.strokeWidth !== void 0 && (!Number.isFinite(a.strokeWidth) || a.strokeWidth < 25e-4 || a.strokeWidth > 0.02)) return null;
|
|
26445
|
+
return { kind: "ink", session, annotation: a };
|
|
26446
|
+
}
|
|
26158
26447
|
if (message.name !== "EPUB_TEXT_SELECTED" || !(0, import_core3.validateAnnotationAnchor)(p.anchor) || p.anchor.kind !== "epub-cfi" || p.text !== p.anchor.quote || !Number.isSafeInteger(p.pageIndex) || p.pageIndex < 1) return null;
|
|
26159
26448
|
if (documentId && p.anchor.documentId && p.anchor.documentId !== documentId) return null;
|
|
26160
26449
|
return { kind: "selection", session, text: p.text, pageIndex: p.pageIndex, anchor: { ...p.anchor, documentId: documentId ?? p.anchor.documentId } };
|
|
@@ -26191,7 +26480,7 @@ var WebViewViewer = ({
|
|
|
26191
26480
|
}) => {
|
|
26192
26481
|
const webViewRef = (0, import_react4.useRef)(null);
|
|
26193
26482
|
const insets = usePapyrusSafeAreaInsets();
|
|
26194
|
-
const { pageTheme, epubReadingMode, setDocumentState, annotations, isLoaded, locale, annotationColor, annotationOpacity, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = (0, import_core4.useViewerStore)();
|
|
26483
|
+
const { pageTheme, epubReadingMode, setDocumentState, annotations, isLoaded, locale, annotationColor, annotationOpacity, inkStrokeWidth, activeTool, activeDrawToolPreset, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = (0, import_core4.useViewerStore)();
|
|
26195
26484
|
const [selection, setSelection] = (0, import_react4.useState)(null);
|
|
26196
26485
|
const t = getStrings(locale);
|
|
26197
26486
|
const bridgeEngine = engine;
|
|
@@ -26276,6 +26565,15 @@ var WebViewViewer = ({
|
|
|
26276
26565
|
if (!isLoaded) return;
|
|
26277
26566
|
webViewRef.current?.postMessage(JSON.stringify({ id: "epub-layout", kind: "set-epub-view-mode", payload: { epubMode: epubReadingMode, documentSessionId: bridgeEngine.getWebViewDocumentSessionId?.() } }));
|
|
26278
26567
|
}, [isLoaded, epubReadingMode, bridgeEngine]);
|
|
26568
|
+
(0, import_react4.useEffect)(() => {
|
|
26569
|
+
if (!isLoaded || documentType !== "epub") return;
|
|
26570
|
+
const inkMode = resolveEpubInkMode({ documentType, isLoaded, activeTool, preset: activeDrawToolPreset, color: annotationColor, opacity: annotationOpacity, strokeWidth: inkStrokeWidth });
|
|
26571
|
+
if (!inkMode) return;
|
|
26572
|
+
webViewRef.current?.postMessage(JSON.stringify({ id: `epub-ink-mode-${Date.now()}`, kind: "set-epub-ink-mode", payload: {
|
|
26573
|
+
...inkMode,
|
|
26574
|
+
documentSessionId: bridgeEngine.getWebViewDocumentSessionId?.()
|
|
26575
|
+
} }));
|
|
26576
|
+
}, [isLoaded, documentType, activeTool, activeDrawToolPreset, annotationColor, annotationOpacity, inkStrokeWidth, bridgeEngine]);
|
|
26279
26577
|
const sendSelectionCommand = (key) => {
|
|
26280
26578
|
webViewRef.current?.postMessage(JSON.stringify({
|
|
26281
26579
|
type: "epub-selection-action",
|
|
@@ -26335,6 +26633,10 @@ var WebViewViewer = ({
|
|
|
26335
26633
|
else setSelectedAnnotation(annotationEvent.id);
|
|
26336
26634
|
return;
|
|
26337
26635
|
}
|
|
26636
|
+
if (annotationEvent?.kind === "ink" && isLoaded && annotationEvent.session === bridgeEngine.getWebViewDocumentSessionId?.()) {
|
|
26637
|
+
addAnnotation(annotationEvent.annotation);
|
|
26638
|
+
setSelection(null);
|
|
26639
|
+
}
|
|
26338
26640
|
const interaction = parseWebViewInteraction(raw);
|
|
26339
26641
|
if (interaction?.kind === "scroll") onScrollOffset?.(interaction.offsetY);
|
|
26340
26642
|
if (interaction?.kind === "tap") onTap?.();
|
|
@@ -32903,7 +33205,7 @@ function buildBottomBarLayout({
|
|
|
32903
33205
|
toolDockOpen
|
|
32904
33206
|
}) {
|
|
32905
33207
|
const leftSlots = [];
|
|
32906
|
-
if (documentType === "pdf") {
|
|
33208
|
+
if (documentType === "pdf" || documentType === "epub") {
|
|
32907
33209
|
leftSlots.push({
|
|
32908
33210
|
key: "annotate",
|
|
32909
33211
|
active: toolDockOpen || activeMobileDestination === "annotate"
|