@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.mjs
CHANGED
|
@@ -20559,7 +20559,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20559
20559
|
var doc=contents.document,win=contents.window,start=null,blocked=false;
|
|
20560
20560
|
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;}
|
|
20561
20561
|
function selected(){return Boolean(String(win.getSelection()||'').trim()) || config.blocked();}
|
|
20562
|
-
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay]'));}
|
|
20562
|
+
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay],[data-papyrus-ink-capture]'));}
|
|
20563
20563
|
function begin(e){start=point(e);blocked=e.touches.length!==1 || selected() || interactive(e.target);}
|
|
20564
20564
|
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();}
|
|
20565
20565
|
function move(e){if(e.touches.length!==1)blocked=true;invalidateScroll(point(e));}
|
|
@@ -20584,6 +20584,84 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20584
20584
|
typeof anchor.href === 'string' && !/^(javascript|data):/i.test(anchor.href) &&
|
|
20585
20585
|
typeof anchor.quote === 'string' && anchor.quote.length > 0 && anchor.quote.length <= 100000;
|
|
20586
20586
|
}
|
|
20587
|
+
function simplifyPath(points, tolerance, maxPoints) {
|
|
20588
|
+
if (!Array.isArray(points) || points.length <= 2) return Array.isArray(points) ? points.slice() : [];
|
|
20589
|
+
tolerance = Number.isFinite(tolerance) ? Math.max(0, tolerance) : 1.5;
|
|
20590
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20591
|
+
var keep = new Uint8Array(points.length); keep[0] = 1; keep[points.length - 1] = 1;
|
|
20592
|
+
var stack = [[0, points.length - 1]], toleranceSquared = tolerance * tolerance;
|
|
20593
|
+
while (stack.length) {
|
|
20594
|
+
var interval = stack.pop(), first = interval[0], last = interval[1], a = points[first], b = points[last];
|
|
20595
|
+
var dx = b.x - a.x, dy = b.y - a.y, lengthSquared = dx * dx + dy * dy, maxDistance = toleranceSquared, split = -1;
|
|
20596
|
+
for (var i = first + 1; i < last; i++) {
|
|
20597
|
+
var p = points[i], ratio = lengthSquared ? Math.max(0, Math.min(1, ((p.x - a.x) * dx + (p.y - a.y) * dy) / lengthSquared)) : 0;
|
|
20598
|
+
var px = a.x + ratio * dx, py = a.y + ratio * dy, ox = p.x - px, oy = p.y - py, distance = ox * ox + oy * oy;
|
|
20599
|
+
if (distance > maxDistance) { maxDistance = distance; split = i; }
|
|
20600
|
+
}
|
|
20601
|
+
if (split >= 0) { keep[split] = 1; stack.push([first, split], [split, last]); }
|
|
20602
|
+
}
|
|
20603
|
+
var result = []; for (var j = 0; j < points.length; j++) if (keep[j]) result.push(points[j]);
|
|
20604
|
+
if (result.length <= maxPoints) return result;
|
|
20605
|
+
var capped = []; for (var k = 0; k < maxPoints; k++) capped.push(result[Math.round(k * (result.length - 1) / (maxPoints - 1))]);
|
|
20606
|
+
return capped;
|
|
20607
|
+
}
|
|
20608
|
+
function compactGesturePoints(points, maxPoints) {
|
|
20609
|
+
if (!Array.isArray(points)) return [];
|
|
20610
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 1024;
|
|
20611
|
+
if (points.length <= maxPoints) return points.slice();
|
|
20612
|
+
var compacted = [];
|
|
20613
|
+
for (var i = 0; i < maxPoints; i++) compacted.push(points[Math.round(i * (points.length - 1) / (maxPoints - 1))]);
|
|
20614
|
+
return compacted;
|
|
20615
|
+
}
|
|
20616
|
+
function densifyPath(points, maxStep, maxPoints) {
|
|
20617
|
+
if (!Array.isArray(points) || !points.length) return [];
|
|
20618
|
+
if (points.length === 1) return points.slice();
|
|
20619
|
+
maxStep = Number.isFinite(maxStep) ? Math.max(1, maxStep) : 12;
|
|
20620
|
+
maxPoints = Number.isSafeInteger(maxPoints) ? Math.max(2, maxPoints) : 512;
|
|
20621
|
+
var cumulative = [0], total = 0;
|
|
20622
|
+
for (var i = 1; i < points.length; i++) {
|
|
20623
|
+
if (![points[i-1].x,points[i-1].y,points[i].x,points[i].y].every(Number.isFinite)) return [];
|
|
20624
|
+
total += Math.hypot(points[i].x-points[i-1].x, points[i].y-points[i-1].y);
|
|
20625
|
+
cumulative.push(total);
|
|
20626
|
+
}
|
|
20627
|
+
if (!total) return [points[0], points[points.length-1]];
|
|
20628
|
+
var intervals = Math.min(maxPoints-1, Math.max(1, Math.ceil(total/maxStep))), result = [], segment = 1;
|
|
20629
|
+
for (var sample = 0; sample <= intervals; sample++) {
|
|
20630
|
+
var distance = total*sample/intervals;
|
|
20631
|
+
while (segment < cumulative.length-1 && cumulative[segment] < distance) segment++;
|
|
20632
|
+
var start = points[segment-1], end = points[segment], span = cumulative[segment]-cumulative[segment-1];
|
|
20633
|
+
var ratio = span ? (distance-cumulative[segment-1])/span : 0;
|
|
20634
|
+
result.push({x:start.x+(end.x-start.x)*ratio,y:start.y+(end.y-start.y)*ratio});
|
|
20635
|
+
}
|
|
20636
|
+
return result;
|
|
20637
|
+
}
|
|
20638
|
+
function createSpatialIndex(entries, cellSize) {
|
|
20639
|
+
cellSize = Number.isFinite(cellSize) ? Math.max(8, cellSize) : 64;
|
|
20640
|
+
var cells = new Map();
|
|
20641
|
+
entries.forEach(function(entry) {
|
|
20642
|
+
var left = Math.floor(entry.left / cellSize), right = Math.floor(entry.right / cellSize);
|
|
20643
|
+
var top = Math.floor(entry.top / cellSize), bottom = Math.floor(entry.bottom / cellSize);
|
|
20644
|
+
for (var x = left; x <= right; x++) for (var y = top; y <= bottom; y++) {
|
|
20645
|
+
var key = x + ':' + y, bucket = cells.get(key); if (!bucket) { bucket = []; cells.set(key, bucket); } bucket.push(entry);
|
|
20646
|
+
}
|
|
20647
|
+
});
|
|
20648
|
+
return {cells:cells,cellSize:cellSize};
|
|
20649
|
+
}
|
|
20650
|
+
function queryNearestTextRect(index, x, y, maxDistance) {
|
|
20651
|
+
if (!index || !Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(maxDistance) || maxDistance < 0) return null;
|
|
20652
|
+
var size = index.cellSize, minX = Math.floor((x-maxDistance)/size), maxX = Math.floor((x+maxDistance)/size);
|
|
20653
|
+
var minY = Math.floor((y-maxDistance)/size), maxY = Math.floor((y+maxDistance)/size), seen = new Set(), best = null;
|
|
20654
|
+
for (var cx=minX; cx<=maxX; cx++) for (var cy=minY; cy<=maxY; cy++) {
|
|
20655
|
+
var bucket = index.cells.get(cx+':'+cy); if (!bucket) continue;
|
|
20656
|
+
bucket.forEach(function(entry) {
|
|
20657
|
+
if (seen.has(entry)) return; seen.add(entry);
|
|
20658
|
+
var nearestX = Math.max(entry.left,Math.min(entry.right,x)), nearestY = Math.max(entry.top,Math.min(entry.bottom,y));
|
|
20659
|
+
var dx=x-nearestX,dy=y-nearestY,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20660
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={entry:entry,distance:distance,x:nearestX,y:nearestY};
|
|
20661
|
+
});
|
|
20662
|
+
}
|
|
20663
|
+
return best;
|
|
20664
|
+
}
|
|
20587
20665
|
function textNodes(document) {
|
|
20588
20666
|
var walker = document.createTreeWalker(document.body, 4);
|
|
20589
20667
|
var nodes = [], text = '', node;
|
|
@@ -20633,13 +20711,196 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20633
20711
|
if(win.getComputedStyle(doc.body).position==='static')doc.body.style.position='relative';
|
|
20634
20712
|
doc.body.appendChild(overlay);
|
|
20635
20713
|
var registry = new Map(), hitRegions = [];
|
|
20714
|
+
var inkRegistry = new Map(), rangeCache = new Map(), spatialIndex = null, activeGesture = null, inkConfig = {enabled:false,preset:'ink'};
|
|
20715
|
+
var inkSvg = doc.createElementNS('http://www.w3.org/2000/svg','svg');
|
|
20716
|
+
inkSvg.setAttribute('data-papyrus-ink-overlay','');
|
|
20717
|
+
inkSvg.style.cssText = 'position:absolute;left:0;top:0;overflow:visible;pointer-events:none;z-index:1';
|
|
20718
|
+
overlay.appendChild(inkSvg);
|
|
20719
|
+
var inkCanvas = doc.createElement('canvas');
|
|
20720
|
+
inkCanvas.dataset.papyrusInkCapture = '';
|
|
20721
|
+
inkCanvas.style.cssText = 'position:fixed;left:0;top:0;width:1px;height:1px;z-index:2147483000;background:transparent;pointer-events:none;touch-action:none';
|
|
20722
|
+
doc.body.appendChild(inkCanvas);
|
|
20723
|
+
var inkContext = null; try { if(typeof win.CanvasRenderingContext2D==='function')inkContext = inkCanvas.getContext('2d'); } catch (_) {}
|
|
20724
|
+
function resizeCanvas() {
|
|
20725
|
+
var bodyRect=doc.body.getBoundingClientRect(), ratio = Math.max(1,Math.min(3,win.devicePixelRatio || 1));
|
|
20726
|
+
var width=Math.max(1,Math.min(4096,doc.body.clientWidth||bodyRect.width||Math.min(4096,win.innerWidth||1)));
|
|
20727
|
+
var height=Math.max(1,Math.min(4096,doc.body.clientHeight||bodyRect.height||Math.min(4096,win.innerHeight||1)));
|
|
20728
|
+
inkCanvas.style.width=width+'px';inkCanvas.style.height=height+'px';
|
|
20729
|
+
inkCanvas.width = Math.round(width*ratio); inkCanvas.height = Math.round(height*ratio);
|
|
20730
|
+
if (inkContext) { inkContext.setTransform(ratio,0,0,ratio,0,0); inkContext.clearRect(0,0,width,height); }
|
|
20731
|
+
}
|
|
20732
|
+
function collectTextRects() {
|
|
20733
|
+
var walker = doc.createTreeWalker(doc.body,4), node, entries=[];
|
|
20734
|
+
while ((node=walker.nextNode())) {
|
|
20735
|
+
var parent=node.parentElement;
|
|
20736
|
+
if (!parent || parent.closest('script,style,noscript,textarea,[data-papyrus-overlay],[data-papyrus-ink-capture]')) continue;
|
|
20737
|
+
var text=node.nodeValue || '', style=win.getComputedStyle(parent), computed=parseFloat(style.lineHeight);
|
|
20738
|
+
for (var start=0; start<text.length;) {
|
|
20739
|
+
var end=Math.min(text.length,start+24), last=text.charCodeAt(end-1), next=text.charCodeAt(end);
|
|
20740
|
+
if(end<text.length&&last>=0xD800&&last<=0xDBFF&&next>=0xDC00&&next<=0xDFFF)end++;
|
|
20741
|
+
var range=doc.createRange(); range.setStart(node,start); range.setEnd(node,end);
|
|
20742
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20743
|
+
rects.forEach(function(rect) {
|
|
20744
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20745
|
+
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,
|
|
20746
|
+
node:node,start:start,end:end,lineHeight:Number.isFinite(computed)&&computed>0?computed:rect.height});
|
|
20747
|
+
});
|
|
20748
|
+
start=end;
|
|
20749
|
+
}
|
|
20750
|
+
}
|
|
20751
|
+
return entries;
|
|
20752
|
+
}
|
|
20753
|
+
function rebuildSpatialIndex() { spatialIndex=createSpatialIndex(collectTextRects(),64); rangeCache.clear(); }
|
|
20754
|
+
function inkViewportExtent() {
|
|
20755
|
+
var root=doc.documentElement,body=doc.body,bodyRect=body.getBoundingClientRect();
|
|
20756
|
+
var width=root.clientWidth||body.clientWidth||bodyRect.width||win.innerWidth||1;
|
|
20757
|
+
var height=root.clientHeight||body.clientHeight||bodyRect.height||win.innerHeight||1;
|
|
20758
|
+
return Math.max(1,Math.min(4096,width),Math.min(4096,height));
|
|
20759
|
+
}
|
|
20760
|
+
function inkStrokeWidthPx(width,preset) {
|
|
20761
|
+
var scale=preset==='highlight'?0.8:preset==='underline'?0.1:0.15;
|
|
20762
|
+
return Math.max(1,Math.min(24,(Number.isFinite(width)?width:0.006)*inkViewportExtent()*scale));
|
|
20763
|
+
}
|
|
20764
|
+
function closestGlyph(entry,x,y,maxDistance) {
|
|
20765
|
+
var source=(entry.node.nodeValue || '').slice(entry.start,entry.end), best=null, offset=0;
|
|
20766
|
+
for (var glyph of source) {
|
|
20767
|
+
var range=doc.createRange(); range.setStart(entry.node,entry.start+offset); range.setEnd(entry.node,entry.start+offset+glyph.length); offset+=glyph.length;
|
|
20768
|
+
var rects=[]; try { rects=Array.from(range.getClientRects()); } catch (_) {}
|
|
20769
|
+
rects.forEach(function(rect) {
|
|
20770
|
+
if (!(rect.width>0 && rect.height>0)) return;
|
|
20771
|
+
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));
|
|
20772
|
+
var dx=x-nx,dy=y-ny,distance=Math.sqrt(dx*dx+dy*dy);
|
|
20773
|
+
if (distance<=maxDistance && (!best || distance<best.distance)) best={range:range,rect:rect,distance:distance};
|
|
20774
|
+
});
|
|
20775
|
+
}
|
|
20776
|
+
if (!best || typeof contents.cfiFromRange!=='function') return null;
|
|
20777
|
+
var quote=best.range.toString(), cfiRange; try { cfiRange=contents.cfiFromRange(best.range); } catch (_) { return null; }
|
|
20778
|
+
if (!quote || typeof cfiRange!=='string' || !/^epubcfi\\([^\\n<>]+\\)$/.test(cfiRange)) return null;
|
|
20779
|
+
var lineHeight=Math.max(1,entry.lineHeight || best.rect.height), px=x-(best.rect.left+win.scrollX), py=y-(best.rect.top+win.scrollY);
|
|
20780
|
+
return {cfiRange:cfiRange,quote:quote,x:Math.max(-3,Math.min(3,px/lineHeight)),y:Math.max(-3,Math.min(3,py/lineHeight))};
|
|
20781
|
+
}
|
|
20782
|
+
function renderInkAnnotation(annotation,keep,bodyRect) {
|
|
20783
|
+
var baseRect=bodyRect || doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20784
|
+
var data=annotation.epubInk;
|
|
20785
|
+
if (!data || data.version!==1 || data.kind!=='epub-ink' || !Array.isArray(data.segments)) return;
|
|
20786
|
+
keep.add(annotation.id);
|
|
20787
|
+
var group=inkRegistry.get(annotation.id);
|
|
20788
|
+
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); }
|
|
20789
|
+
group.replaceChildren();
|
|
20790
|
+
var color=/^#[0-9a-f]{6}$/i.test(annotation.color)?annotation.color:'#2563eb';
|
|
20791
|
+
var opacity=Number.isFinite(annotation.opacity)?Math.max(0,Math.min(1,annotation.opacity)):1;
|
|
20792
|
+
var preset=['ink','highlight','underline'].indexOf(data.preset)>=0?data.preset:'ink';
|
|
20793
|
+
var stroke=inkStrokeWidthPx(annotation.strokeWidth,preset);
|
|
20794
|
+
data.segments.forEach(function(segment) {
|
|
20795
|
+
if (segment.href!==options.href || !Array.isArray(segment.points)) return;
|
|
20796
|
+
var paths=[], current=[];
|
|
20797
|
+
segment.points.forEach(function(point) {
|
|
20798
|
+
var range=rangeCache.get(point.cfiRange);
|
|
20799
|
+
if (!range) { try { range=contents.range(point.cfiRange); } catch (_) { range=null; } if (range) rangeCache.set(point.cfiRange,range); }
|
|
20800
|
+
if (!range || range.toString()!==point.quote) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20801
|
+
var rect; try { rect=range.getBoundingClientRect(); } catch (_) { rect=null; }
|
|
20802
|
+
if (!rect || !(rect.width>0 && rect.height>0)) { if(current.length>1)paths.push(current);current=[];return; }
|
|
20803
|
+
var lineHeight=Math.max(1,rect.height), x=rect.left-baseRect.left+point.x*lineHeight, y=rect.top-baseRect.top+point.y*lineHeight;
|
|
20804
|
+
var previous=current[current.length-1], jumpLimit=Math.max(24,lineHeight*2.5);
|
|
20805
|
+
if (previous && Math.hypot(x-previous.x,y-previous.y)>jumpLimit) { if(current.length>1)paths.push(current);current=[]; }
|
|
20806
|
+
current.push({x:x,y:y,lineHeight:lineHeight});
|
|
20807
|
+
});
|
|
20808
|
+
if(current.length>1)paths.push(current);
|
|
20809
|
+
paths.forEach(function(points) {
|
|
20810
|
+
var d='M '+points[0].x.toFixed(1)+' '+points[0].y.toFixed(1);
|
|
20811
|
+
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);}
|
|
20812
|
+
var last=points[points.length-1];d+=' L '+last.x.toFixed(1)+' '+last.y.toFixed(1);
|
|
20813
|
+
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);
|
|
20814
|
+
});
|
|
20815
|
+
});
|
|
20816
|
+
}
|
|
20817
|
+
function clearPreview() {
|
|
20818
|
+
if(inkContext)inkContext.clearRect(0,0,inkCanvas.width,inkCanvas.height);
|
|
20819
|
+
inkSvg.querySelectorAll('[data-papyrus-ink-preview]').forEach(function(path){path.remove();});
|
|
20820
|
+
}
|
|
20821
|
+
function createPreviewPath(x,y) {
|
|
20822
|
+
var path=doc.createElementNS('http://www.w3.org/2000/svg','path');
|
|
20823
|
+
path.setAttribute('data-papyrus-ink-preview','');path.setAttribute('d','M '+x.toFixed(1)+' '+y.toFixed(1));path.setAttribute('fill','none');
|
|
20824
|
+
path.setAttribute('stroke',inkConfig.color);path.setAttribute('stroke-width',String(inkStrokeWidthPx(inkConfig.strokeWidth,inkConfig.preset)));
|
|
20825
|
+
path.setAttribute('stroke-linecap','round');path.setAttribute('stroke-linejoin','round');path.setAttribute('opacity',String(inkConfig.opacity));
|
|
20826
|
+
path.style.pointerEvents='none';inkSvg.appendChild(path);return path;
|
|
20827
|
+
}
|
|
20828
|
+
function updatePreviewPath(clientX,clientY) {
|
|
20829
|
+
var bodyRect=doc.body.getBoundingClientRect(),x=clientX-bodyRect.left,y=clientY-bodyRect.top;
|
|
20830
|
+
var gesture=activeGesture;
|
|
20831
|
+
if(!gesture.previewPath||gesture.previewPathPoints>=32){
|
|
20832
|
+
gesture.previewPath=createPreviewPath(gesture.previewLast?gesture.previewLast.x:x,gesture.previewLast?gesture.previewLast.y:y);
|
|
20833
|
+
gesture.previewPathPoints=1;
|
|
20834
|
+
}
|
|
20835
|
+
var pathData=gesture.previewPath.getAttribute('d')||'';
|
|
20836
|
+
gesture.previewPath.setAttribute('d',pathData+' L '+x.toFixed(1)+' '+y.toFixed(1));
|
|
20837
|
+
gesture.previewPathPoints++;
|
|
20838
|
+
gesture.previewLast={x:x,y:y};
|
|
20839
|
+
}
|
|
20840
|
+
function cancelGesture() {
|
|
20841
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20842
|
+
if(gesture)try{inkCanvas.releasePointerCapture(gesture.pointerId);}catch(_){}
|
|
20843
|
+
}
|
|
20844
|
+
function commitGesture() {
|
|
20845
|
+
var gesture=activeGesture; activeGesture=null; clearPreview();
|
|
20846
|
+
if(!gesture || !alive || !options.isCurrent() || !inkConfig.enabled || !spatialIndex) return;
|
|
20847
|
+
var simplified=simplifyPath(gesture.points,1.5,512), anchorSamples=densifyPath(simplified,12,512), segments=[], current=[];
|
|
20848
|
+
anchorSamples.forEach(function(point) {
|
|
20849
|
+
var coarse=queryNearestTextRect(spatialIndex,point.x,point.y,28);
|
|
20850
|
+
var cutoff=coarse?Math.max(12,Math.min(28,0.8*coarse.entry.lineHeight)):12;
|
|
20851
|
+
var anchored=coarse && closestGlyph(coarse.entry,point.x,point.y,cutoff);
|
|
20852
|
+
if(!anchored){if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});current=[];return;}
|
|
20853
|
+
current.push(anchored);
|
|
20854
|
+
});
|
|
20855
|
+
if(current.length>1)segments.push({href:options.href,spineIndex:options.spineIndex,points:current});
|
|
20856
|
+
segments=segments.slice(0,64);
|
|
20857
|
+
var pointCount=segments.reduce(function(total,segment){return total+segment.points.length;},0);
|
|
20858
|
+
if(!pointCount)return;
|
|
20859
|
+
var width=Math.max(1,doc.documentElement.scrollWidth,win.innerWidth),height=Math.max(1,doc.documentElement.scrollHeight,win.innerHeight);
|
|
20860
|
+
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))};});
|
|
20861
|
+
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;}));
|
|
20862
|
+
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;}));
|
|
20863
|
+
var first=segments[0].points[0], href=segments[0].href, documentId=typeof options.documentId==='function'?options.documentId():options.documentId;
|
|
20864
|
+
var annotation={id:'epub-ink-'+Date.now()+'-'+Math.random().toString(36).slice(2,9),type:'ink',pageIndex:(options.spineIndex||0)+1,
|
|
20865
|
+
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,
|
|
20866
|
+
anchor:{version:1,kind:'epub-cfi',cfiRange:first.cfiRange,href:href,spineIndex:options.spineIndex,documentId:documentId,quote:first.quote},
|
|
20867
|
+
epubInk:{version:1,kind:'epub-ink',documentId:documentId,preset:inkConfig.preset,segments:segments}};
|
|
20868
|
+
if(typeof options.onInkCommit==='function')options.onInkCommit(annotation);
|
|
20869
|
+
}
|
|
20870
|
+
function pointerDown(event) {
|
|
20871
|
+
if(!inkConfig.enabled || !alive || !options.isCurrent() || event.button!==undefined && event.button!==0)return;
|
|
20872
|
+
if(activeGesture){cancelGesture();return;}
|
|
20873
|
+
event.preventDefault();event.stopPropagation();
|
|
20874
|
+
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};
|
|
20875
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20876
|
+
try{inkCanvas.setPointerCapture(event.pointerId);}catch(_){}
|
|
20877
|
+
}
|
|
20878
|
+
function pointerMove(event) {
|
|
20879
|
+
if(!activeGesture || activeGesture.pointerId!==event.pointerId)return;
|
|
20880
|
+
if(!options.isCurrent()||!inkConfig.enabled){cancelGesture();return;}
|
|
20881
|
+
event.preventDefault();event.stopPropagation();
|
|
20882
|
+
var point={x:event.clientX+win.scrollX,y:event.clientY+win.scrollY};activeGesture.points.push(point);
|
|
20883
|
+
if(activeGesture.points.length>2048)activeGesture.points=compactGesturePoints(activeGesture.points,1024);
|
|
20884
|
+
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();}
|
|
20885
|
+
updatePreviewPath(event.clientX,event.clientY);
|
|
20886
|
+
activeGesture.last={x:event.clientX,y:event.clientY};
|
|
20887
|
+
}
|
|
20888
|
+
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();}
|
|
20889
|
+
function pointerCancel(event) {if(activeGesture && (event.pointerId===undefined || activeGesture.pointerId===event.pointerId))cancelGesture();}
|
|
20890
|
+
resizeCanvas();rebuildSpatialIndex();
|
|
20891
|
+
inkCanvas.addEventListener('pointerdown',pointerDown);inkCanvas.addEventListener('pointermove',pointerMove);inkCanvas.addEventListener('pointerup',pointerUp);inkCanvas.addEventListener('pointercancel',pointerCancel);inkCanvas.addEventListener('lostpointercapture',pointerCancel);
|
|
20892
|
+
win.addEventListener('blur',pointerCancel);win.addEventListener('resize',resizeCanvas);
|
|
20636
20893
|
function render() {
|
|
20637
20894
|
frame = 0; if (!alive || !options.isCurrent()) return;
|
|
20638
|
-
var keep = new Set(), noteGroups = new Map();
|
|
20895
|
+
var keep = new Set(), keepInk = new Set(), noteGroups = new Map();
|
|
20639
20896
|
hitRegions = [];
|
|
20897
|
+
var bodyRect=doc.body.getBoundingClientRect() || {left:0,top:0};
|
|
20898
|
+
inkSvg.setAttribute('width',String(Math.max(doc.documentElement.scrollWidth,win.innerWidth)));
|
|
20899
|
+
inkSvg.setAttribute('height',String(Math.max(doc.documentElement.scrollHeight,win.innerHeight)));
|
|
20640
20900
|
options.annotations().forEach(function(annotation) {
|
|
20641
20901
|
var anchor = annotation.anchor;
|
|
20642
20902
|
if (!validAnchor(anchor) || anchor.href !== options.href || anchor.documentId && options.documentId && anchor.documentId !== options.documentId) return;
|
|
20903
|
+
if(annotation.type==='ink' && annotation.epubInk){renderInkAnnotation(annotation,keepInk,bodyRect);return;}
|
|
20643
20904
|
var range = resolveRange(contents,anchor); if (!range) return;
|
|
20644
20905
|
var rects = Array.from(range.getClientRects()).filter(function(r){return r.width>0 && r.height>0;});
|
|
20645
20906
|
if (!rects.length) return;
|
|
@@ -20678,22 +20939,26 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20678
20939
|
group.button.addEventListener('click',function(e){e.stopPropagation();if(options.isCurrent())options.onTap(group.ids[0],group.ids);});
|
|
20679
20940
|
});
|
|
20680
20941
|
registry.forEach(function(group,id){if (!keep.has(id)) {group.remove();registry.delete(id);}});
|
|
20942
|
+
inkRegistry.forEach(function(group,id){if (!keepInk.has(id)) {group.remove();inkRegistry.delete(id);}});
|
|
20681
20943
|
}
|
|
20682
20944
|
function schedule() { if (alive && !frame) frame = win.requestAnimationFrame(render); }
|
|
20945
|
+
function rebuildAndSchedule(){if(!alive)return;rebuildSpatialIndex();schedule();}
|
|
20946
|
+
function handleResize(){resizeCanvas();rebuildAndSchedule();}
|
|
20947
|
+
function handleDocumentLoad(){rebuildAndSchedule();}
|
|
20683
20948
|
function tapMarkup(event) {
|
|
20684
20949
|
if(!alive || !options.isCurrent() || String(win.getSelection() || '').length || event.target.closest('[data-papyrus-overlay]'))return;
|
|
20685
20950
|
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;});});
|
|
20686
20951
|
if(hit) {event.stopPropagation();options.onTap(hit.id);}
|
|
20687
20952
|
}
|
|
20688
20953
|
doc.addEventListener('click',tapMarkup);
|
|
20689
|
-
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(
|
|
20954
|
+
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(rebuildAndSchedule) : null;
|
|
20690
20955
|
if (observer) observer.observe(doc.body);
|
|
20691
|
-
win.addEventListener('resize',
|
|
20692
|
-
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20956
|
+
win.addEventListener('resize',handleResize);win.addEventListener('scroll',schedule); doc.addEventListener('load',handleDocumentLoad,true);
|
|
20957
|
+
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(function(){if(alive){rebuildSpatialIndex();schedule();}});
|
|
20693
20958
|
schedule();
|
|
20694
|
-
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',
|
|
20959
|
+
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();}};
|
|
20695
20960
|
}
|
|
20696
|
-
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20961
|
+
return {validAnchor:validAnchor,simplifyPath:simplifyPath,compactGesturePoints:compactGesturePoints,densifyPath:densifyPath,createSpatialIndex:createSpatialIndex,queryNearestTextRect:queryNearestTextRect,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20697
20962
|
});
|
|
20698
20963
|
|
|
20699
20964
|
/* @papyrus-epub-annotations:end */
|
|
@@ -20709,6 +20974,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20709
20974
|
let annotationDocumentId;
|
|
20710
20975
|
let annotationLabels = {};
|
|
20711
20976
|
let epubAnnotations = [];
|
|
20977
|
+
let epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
20712
20978
|
const epubAnnotationRenderers = new Map();
|
|
20713
20979
|
let spineItems = [];
|
|
20714
20980
|
let textPages = [];
|
|
@@ -21823,11 +22089,14 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21823
22089
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21824
22090
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21825
22091
|
href, get documentId() { return annotationDocumentId; },
|
|
22092
|
+
spineIndex:contents.sectionIndex,
|
|
21826
22093
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
21827
22094
|
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21828
22095
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
22096
|
+
onInkCommit: annotation => sendEvent('EPUB_INK_CREATED',{documentSessionId:session,annotation}),
|
|
21829
22097
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21830
22098
|
});
|
|
22099
|
+
renderer.setInkMode(epubInkMode);
|
|
21831
22100
|
epubAnnotationRenderers.set(contents,renderer);
|
|
21832
22101
|
}
|
|
21833
22102
|
const frame = contents && contents.document ? contents.document.defaultView.frameElement : null;
|
|
@@ -21919,7 +22188,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21919
22188
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21920
22189
|
});
|
|
21921
22190
|
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
21922
|
-
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22191
|
+
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => name==='relocated'?renderer.schedule():renderer.invalidateLayout());
|
|
21923
22192
|
}));
|
|
21924
22193
|
rendition.on('relocated', (location) => {
|
|
21925
22194
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
@@ -22216,6 +22485,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22216
22485
|
documentSessionId = payload.documentSessionId || null;
|
|
22217
22486
|
epubAnnotations = [];
|
|
22218
22487
|
annotationDocumentId = undefined;
|
|
22488
|
+
epubInkMode = {enabled:false,color:'#2563eb',opacity:1,strokeWidth:0.006};
|
|
22219
22489
|
zoom = 1.0;
|
|
22220
22490
|
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22221
22491
|
epubLocation = null;
|
|
@@ -22347,6 +22617,12 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22347
22617
|
}
|
|
22348
22618
|
sendResponse(id,true,null);return;
|
|
22349
22619
|
}
|
|
22620
|
+
if (kind === 'set-epub-ink-mode') {
|
|
22621
|
+
if(currentType!=='epub'||!documentSessionId||payload.documentSessionId!==documentSessionId)throw new Error('Stale EPUB ink session');
|
|
22622
|
+
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};
|
|
22623
|
+
epubAnnotationRenderers.forEach(renderer=>renderer.setInkMode(epubInkMode));
|
|
22624
|
+
sendResponse(id,true,null);return;
|
|
22625
|
+
}
|
|
22350
22626
|
if(kind === 'epub-go-to-location'){
|
|
22351
22627
|
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22352
22628
|
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>{if(payload.documentSessionId!==documentSessionId)return;epubResizeAnchor?.invalidate();return rendition.display(payload.cfi);});
|
|
@@ -25936,9 +26212,15 @@ var parseWebViewInteraction = (raw) => {
|
|
|
25936
26212
|
};
|
|
25937
26213
|
|
|
25938
26214
|
// components/epubAnnotationEvents.ts
|
|
25939
|
-
import { validateAnnotationAnchor } from "@papyrus-sdk/core";
|
|
26215
|
+
import { validateAnnotationAnchor, validateEpubInkData } from "@papyrus-sdk/core";
|
|
26216
|
+
var EPUB_INK_PRESETS = ["ink", "highlight", "underline"];
|
|
26217
|
+
function resolveEpubInkMode(input) {
|
|
26218
|
+
if (!input.isLoaded || input.documentType !== "epub") return null;
|
|
26219
|
+
const preset = EPUB_INK_PRESETS.includes(input.preset) ? input.preset : "ink";
|
|
26220
|
+
return { enabled: input.activeTool === "ink" && EPUB_INK_PRESETS.includes(input.preset), preset, color: input.color, opacity: input.opacity, strokeWidth: input.strokeWidth };
|
|
26221
|
+
}
|
|
25940
26222
|
function parseEpubAnnotationEvent(raw, session, documentId) {
|
|
25941
|
-
if (!session || raw.length >
|
|
26223
|
+
if (!session || raw.length > 75e4) return null;
|
|
25942
26224
|
let message;
|
|
25943
26225
|
try {
|
|
25944
26226
|
message = JSON.parse(raw);
|
|
@@ -25948,6 +26230,13 @@ function parseEpubAnnotationEvent(raw, session, documentId) {
|
|
|
25948
26230
|
const p = message?.payload;
|
|
25949
26231
|
if (message?.type !== "event" || !p || p.documentSessionId !== session) return null;
|
|
25950
26232
|
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;
|
|
26233
|
+
if (message.name === "EPUB_INK_CREATED") {
|
|
26234
|
+
const a = p.annotation, sidecar = a?.epubInk, first = sidecar?.segments?.[0], point = first?.points?.[0];
|
|
26235
|
+
if (!a || a.type !== "ink" || typeof a.id !== "string" || !a.id || a.id.length > 256 || !Number.isSafeInteger(a.pageIndex) || a.pageIndex < 1 || !validateAnnotationAnchor(a.anchor) || a.anchor.kind !== "epub-cfi" || !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;
|
|
26236
|
+
const rect = a.rect, path = a.path;
|
|
26237
|
+
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;
|
|
26238
|
+
return { kind: "ink", session, annotation: a };
|
|
26239
|
+
}
|
|
25951
26240
|
if (message.name !== "EPUB_TEXT_SELECTED" || !validateAnnotationAnchor(p.anchor) || p.anchor.kind !== "epub-cfi" || p.text !== p.anchor.quote || !Number.isSafeInteger(p.pageIndex) || p.pageIndex < 1) return null;
|
|
25952
26241
|
if (documentId && p.anchor.documentId && p.anchor.documentId !== documentId) return null;
|
|
25953
26242
|
return { kind: "selection", session, text: p.text, pageIndex: p.pageIndex, anchor: { ...p.anchor, documentId: documentId ?? p.anchor.documentId } };
|
|
@@ -25984,7 +26273,7 @@ var WebViewViewer = ({
|
|
|
25984
26273
|
}) => {
|
|
25985
26274
|
const webViewRef = useRef2(null);
|
|
25986
26275
|
const insets = usePapyrusSafeAreaInsets();
|
|
25987
|
-
const { pageTheme, epubReadingMode, setDocumentState, annotations, isLoaded, locale, annotationColor, annotationOpacity, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = useViewerStore2();
|
|
26276
|
+
const { pageTheme, epubReadingMode, setDocumentState, annotations, isLoaded, locale, annotationColor, annotationOpacity, inkStrokeWidth, activeTool, activeDrawToolPreset, addAnnotation, beginAnnotationDraft, setSelectedAnnotation } = useViewerStore2();
|
|
25988
26277
|
const [selection, setSelection] = useState2(null);
|
|
25989
26278
|
const t = getStrings(locale);
|
|
25990
26279
|
const bridgeEngine = engine;
|
|
@@ -26069,6 +26358,15 @@ var WebViewViewer = ({
|
|
|
26069
26358
|
if (!isLoaded) return;
|
|
26070
26359
|
webViewRef.current?.postMessage(JSON.stringify({ id: "epub-layout", kind: "set-epub-view-mode", payload: { epubMode: epubReadingMode, documentSessionId: bridgeEngine.getWebViewDocumentSessionId?.() } }));
|
|
26071
26360
|
}, [isLoaded, epubReadingMode, bridgeEngine]);
|
|
26361
|
+
useEffect2(() => {
|
|
26362
|
+
if (!isLoaded || documentType !== "epub") return;
|
|
26363
|
+
const inkMode = resolveEpubInkMode({ documentType, isLoaded, activeTool, preset: activeDrawToolPreset, color: annotationColor, opacity: annotationOpacity, strokeWidth: inkStrokeWidth });
|
|
26364
|
+
if (!inkMode) return;
|
|
26365
|
+
webViewRef.current?.postMessage(JSON.stringify({ id: `epub-ink-mode-${Date.now()}`, kind: "set-epub-ink-mode", payload: {
|
|
26366
|
+
...inkMode,
|
|
26367
|
+
documentSessionId: bridgeEngine.getWebViewDocumentSessionId?.()
|
|
26368
|
+
} }));
|
|
26369
|
+
}, [isLoaded, documentType, activeTool, activeDrawToolPreset, annotationColor, annotationOpacity, inkStrokeWidth, bridgeEngine]);
|
|
26072
26370
|
const sendSelectionCommand = (key) => {
|
|
26073
26371
|
webViewRef.current?.postMessage(JSON.stringify({
|
|
26074
26372
|
type: "epub-selection-action",
|
|
@@ -26128,6 +26426,10 @@ var WebViewViewer = ({
|
|
|
26128
26426
|
else setSelectedAnnotation(annotationEvent.id);
|
|
26129
26427
|
return;
|
|
26130
26428
|
}
|
|
26429
|
+
if (annotationEvent?.kind === "ink" && isLoaded && annotationEvent.session === bridgeEngine.getWebViewDocumentSessionId?.()) {
|
|
26430
|
+
addAnnotation(annotationEvent.annotation);
|
|
26431
|
+
setSelection(null);
|
|
26432
|
+
}
|
|
26131
26433
|
const interaction = parseWebViewInteraction(raw);
|
|
26132
26434
|
if (interaction?.kind === "scroll") onScrollOffset?.(interaction.offsetY);
|
|
26133
26435
|
if (interaction?.kind === "tap") onTap?.();
|
|
@@ -32747,7 +33049,7 @@ function buildBottomBarLayout({
|
|
|
32747
33049
|
toolDockOpen
|
|
32748
33050
|
}) {
|
|
32749
33051
|
const leftSlots = [];
|
|
32750
|
-
if (documentType === "pdf") {
|
|
33052
|
+
if (documentType === "pdf" || documentType === "epub") {
|
|
32751
33053
|
leftSlots.push({
|
|
32752
33054
|
key: "annotate",
|
|
32753
33055
|
active: toolDockOpen || activeMobileDestination === "annotate"
|