@papyrus-sdk/ui-react-native 0.2.35-beta.11 → 0.2.35-beta.11.epub.2
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/LICENSE +21 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +415 -231
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +359 -175
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
- package/runtime/comicRuntime.test.ts +9 -9
- package/runtime/epubAnnotations.js +7 -4
- package/runtime/epubAnnotations.test.ts +6 -2
- package/runtime/epubReader.js +58 -0
- package/runtime/epubReader.test.ts +74 -0
- package/runtime/epubRuntime.test.ts +45 -0
- package/runtime/index.html +178 -91
- package/runtime/runtime.js +178 -91
- package/runtime/syncComicRuntime.mjs +6 -3
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]'));}
|
|
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();
|
|
@@ -20561,6 +20622,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20561
20622
|
var color = /^#[0-9a-f]{6}$/i.test(annotation.color) ? annotation.color : '#FFC928';
|
|
20562
20623
|
var style = annotation.markupStyle || annotation.type;
|
|
20563
20624
|
var opacity = Number.isFinite(annotation.opacity) ? Math.max(0,Math.min(1,annotation.opacity)) : 0.35;
|
|
20625
|
+
if(style === 'highlight')opacity=Math.min(0.35,opacity);
|
|
20564
20626
|
rects.forEach(function(rect) {
|
|
20565
20627
|
var mark = doc.createElement('div');
|
|
20566
20628
|
var bodyRect=doc.body.getBoundingClientRect();
|
|
@@ -20573,8 +20635,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20573
20635
|
if (hasNote) {
|
|
20574
20636
|
var last = rects[rects.length-1], button = doc.createElement('button');
|
|
20575
20637
|
button.textContent = '●'; button.setAttribute('aria-label',options.labels().comment || '');
|
|
20576
|
-
|
|
20577
|
-
var
|
|
20638
|
+
var pageWidth=Math.max(44, options.pageWidth ? options.pageWidth() : win.innerWidth);
|
|
20639
|
+
var bodyRect=doc.body.getBoundingClientRect(), column=Math.max(0,Math.floor((last.left-bodyRect.left)/pageWidth));
|
|
20640
|
+
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';
|
|
20641
|
+
var key = column+":"+Math.floor(last.top/44);
|
|
20578
20642
|
var neighbors=noteGroups.get(key);
|
|
20579
20643
|
if(!neighbors){neighbors={button:button,ids:[]};noteGroups.set(key,neighbors);group.appendChild(button);}
|
|
20580
20644
|
neighbors.ids.push(annotation.id);
|
|
@@ -20595,10 +20659,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20595
20659
|
doc.addEventListener('click',tapMarkup);
|
|
20596
20660
|
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(schedule) : null;
|
|
20597
20661
|
if (observer) observer.observe(doc.body);
|
|
20598
|
-
win.addEventListener('resize',schedule); doc.addEventListener('load',schedule,true);
|
|
20662
|
+
win.addEventListener('resize',schedule);win.addEventListener('scroll',schedule); doc.addEventListener('load',schedule,true);
|
|
20599
20663
|
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20600
20664
|
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',schedule,true);doc.removeEventListener('click',tapMarkup);overlay.remove();doc.body.style.position=originalPosition;registry.clear();}};
|
|
20665
|
+
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',schedule);win.removeEventListener('scroll',schedule);doc.removeEventListener('load',schedule,true);doc.removeEventListener('click',tapMarkup);overlay.remove();doc.body.style.position=originalPosition;registry.clear();}};
|
|
20602
20666
|
}
|
|
20603
20667
|
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20604
20668
|
});
|
|
@@ -20611,6 +20675,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20611
20675
|
let currentType = null;
|
|
20612
20676
|
let book = null;
|
|
20613
20677
|
let rendition = null;
|
|
20678
|
+
let epubResizeAnchor = null;
|
|
20614
20679
|
let documentSessionId = null;
|
|
20615
20680
|
let annotationDocumentId;
|
|
20616
20681
|
let annotationLabels = {};
|
|
@@ -21023,6 +21088,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21023
21088
|
};
|
|
21024
21089
|
|
|
21025
21090
|
const clearViewer = () => {
|
|
21091
|
+
if(epubResizeAnchor){epubResizeAnchor.destroy();epubResizeAnchor=null;}
|
|
21026
21092
|
epubAnnotationRenderers.forEach(renderer => renderer.destroy());
|
|
21027
21093
|
epubAnnotationRenderers.clear();
|
|
21028
21094
|
if (epubInteractionCleanup) {
|
|
@@ -21679,26 +21745,57 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21679
21745
|
pageCount,
|
|
21680
21746
|
});
|
|
21681
21747
|
|
|
21748
|
+
if (book.locations?.generate) {
|
|
21749
|
+
const activeBook=book;
|
|
21750
|
+
activeBook.locations.generate(150).then(() => {
|
|
21751
|
+
if (isCurrentLoad() && activeBook===book && epubLocation) {
|
|
21752
|
+
epubLocation.progress=activeBook.locations.percentageFromCfi(epubLocation.cfi);
|
|
21753
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
21754
|
+
}
|
|
21755
|
+
}).catch(() => {});
|
|
21756
|
+
}
|
|
21757
|
+
return renderEpubRendition(loadId,generation,null);
|
|
21758
|
+
};
|
|
21759
|
+
|
|
21760
|
+
const renderEpubRendition = async (loadId,generation,target) => {
|
|
21761
|
+
const diagnosticPayload={loadId};
|
|
21762
|
+
const isCurrentLoad=()=>generation===epubLoadGeneration;
|
|
21763
|
+
if(epubInteractionCleanup)epubInteractionCleanup();
|
|
21764
|
+
if(rendition)rendition.destroy();
|
|
21682
21765
|
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
|
-
});
|
|
21766
|
+
rendition = book.renderTo(viewer, window.PapyrusEpubReader.options(epubViewMode === 'single' ? 'paged' : 'chapter-scroll'));
|
|
21691
21767
|
sendEpubDiagnostic('epub.rendition.created', diagnosticPayload);
|
|
21692
21768
|
|
|
21693
21769
|
if (rendition && rendition.hooks && rendition.hooks.content) {
|
|
21694
21770
|
const session = documentSessionId;
|
|
21695
21771
|
const activeRendition = rendition;
|
|
21696
21772
|
rendition.hooks.content.register((contents) => {
|
|
21773
|
+
const removeGestureListeners = window.PapyrusEpubReader.install(contents, {
|
|
21774
|
+
mode: () => epubViewMode === 'single' ? 'paged' : 'chapter-scroll',
|
|
21775
|
+
rtl: () => book.package?.metadata?.direction === 'rtl' || book.spine?.direction === 'rtl',
|
|
21776
|
+
blocked: () => Boolean(nativeMenuSelection && String(nativeMenuSelection.contents?.window?.getSelection() || '').trim()),
|
|
21777
|
+
annotationHit: point => epubAnnotationRenderers.get(contents)?.hit(point.x,point.y),
|
|
21778
|
+
current: () => session === documentSessionId && activeRendition === rendition,
|
|
21779
|
+
interact: () => epubResizeAnchor?.invalidate(),
|
|
21780
|
+
tap: () => sendEvent('EPUB_CONTENT_TAP',{documentSessionId:session}),
|
|
21781
|
+
turn: direction => {
|
|
21782
|
+
epubNavigationQueue = epubNavigationQueue.catch(()=>{}).then(() => {
|
|
21783
|
+
if(session !== documentSessionId || activeRendition !== rendition)return;
|
|
21784
|
+
epubResizeAnchor?.invalidate();
|
|
21785
|
+
return direction<0?activeRendition.prev():activeRendition.next();
|
|
21786
|
+
});
|
|
21787
|
+
epubNavigationQueue.catch(error => sendEvent('EPUB_NAVIGATION_ERROR',{message:String(error)}));
|
|
21788
|
+
},
|
|
21789
|
+
});
|
|
21790
|
+
const gestureCleanup = () => {removeGestureListeners();epubSelectionCleanups.delete(gestureCleanup);};
|
|
21791
|
+
epubSelectionCleanups.add(gestureCleanup);
|
|
21792
|
+
contents.__papyrusGestureCleanup=gestureCleanup;
|
|
21697
21793
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21698
21794
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21699
21795
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21700
21796
|
href, get documentId() { return annotationDocumentId; },
|
|
21701
21797
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
21798
|
+
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21702
21799
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
21703
21800
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21704
21801
|
});
|
|
@@ -21717,8 +21814,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21717
21814
|
typeof selectionWindow.getSelection === 'function'
|
|
21718
21815
|
) {
|
|
21719
21816
|
let selectionTimer = null;
|
|
21720
|
-
|
|
21721
|
-
let lastSelectionAt = 0;
|
|
21817
|
+
|
|
21722
21818
|
const reportSelection = () => {
|
|
21723
21819
|
selectionTimer = null;
|
|
21724
21820
|
if (session !== documentSessionId || activeRendition !== rendition) return;
|
|
@@ -21733,11 +21829,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21733
21829
|
try { cfi = contents.cfiFromRange(range); } catch (_) { return; }
|
|
21734
21830
|
const anchor = window.PapyrusEpubAnnotations?.selection(contents, cfi, href, annotationDocumentId);
|
|
21735
21831
|
if (!anchor) return;
|
|
21736
|
-
|
|
21737
|
-
const now = Date.now();
|
|
21738
|
-
if (key === lastSelectionKey && now - lastSelectionAt < 750) return;
|
|
21739
|
-
lastSelectionKey = key;
|
|
21740
|
-
lastSelectionAt = now;
|
|
21832
|
+
if (nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21741
21833
|
const payload = {documentSessionId: session, text: anchor.quote,
|
|
21742
21834
|
pageIndex: contents.sectionIndex + 1, anchor};
|
|
21743
21835
|
nativeMenuSelection = {contents, payload};
|
|
@@ -21752,6 +21844,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21752
21844
|
// The content document still emits selectionchange, so resolve its
|
|
21753
21845
|
// live Range to a CFI before the native menu action can fire.
|
|
21754
21846
|
if (text) reportSelection();
|
|
21847
|
+
else if (nativeMenuSelection?.contents === contents) nativeMenuSelection = null;
|
|
21755
21848
|
};
|
|
21756
21849
|
selectionDocument.addEventListener('selectionchange', handleSelectionChange);
|
|
21757
21850
|
const selectionCleanup = () => {
|
|
@@ -21774,6 +21867,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21774
21867
|
typeof rendition.hooks.unloaded.register === 'function'
|
|
21775
21868
|
) {
|
|
21776
21869
|
rendition.hooks.unloaded.register((view) => {
|
|
21870
|
+
view?.contents?.__papyrusGestureCleanup?.();
|
|
21777
21871
|
const cleanup = view && view.contents && view.contents.__papyrusSelectionCleanup;
|
|
21778
21872
|
if (typeof cleanup === 'function') cleanup();
|
|
21779
21873
|
const renderer = epubAnnotationRenderers.get(view?.contents);
|
|
@@ -21789,13 +21883,13 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21789
21883
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
21790
21884
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21791
21885
|
const anchor = href && window.PapyrusEpubAnnotations?.selection(contents,cfiRange,href,annotationDocumentId);
|
|
21792
|
-
if (!anchor) return;
|
|
21886
|
+
if (!anchor || nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21793
21887
|
epubScrollDiagnostics && epubScrollDiagnostics.setSelectionActive(true);
|
|
21794
21888
|
const payload = {documentSessionId: selectionSession, text: anchor.quote, pageIndex: contents.sectionIndex+1, anchor};
|
|
21795
21889
|
nativeMenuSelection = {contents, payload};
|
|
21796
21890
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21797
21891
|
});
|
|
21798
|
-
['rendered','resized','layout'].forEach(name => rendition.on(name, () => {
|
|
21892
|
+
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
21799
21893
|
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
21800
21894
|
}));
|
|
21801
21895
|
rendition.on('relocated', (location) => {
|
|
@@ -21805,6 +21899,21 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21805
21899
|
if (index < 0 && start && start.href) index = getSpineIndexByHref(start.href);
|
|
21806
21900
|
if (index < 0 || index >= spineItems.length) return;
|
|
21807
21901
|
epubScrollDiagnostics && epubScrollDiagnostics.relocated(location);
|
|
21902
|
+
let pageGeometry;
|
|
21903
|
+
const manager=rendition.manager,layout=manager?.layout;
|
|
21904
|
+
if(epubViewMode==='single' && layout?.divisor===1 && !manager?.settings?.fullsize && manager?.settings?.direction==='ltr'){
|
|
21905
|
+
const visible=manager.visible?.();
|
|
21906
|
+
const view=visible?.find(view=>view.index===index);
|
|
21907
|
+
if(view && manager.container){
|
|
21908
|
+
pageGeometry={direction:'ltr',firstIndex:book.spine.first()?.index,lastIndex:book.spine.last()?.index,pageWidth:layout.pageWidth,offset:manager.container.getBoundingClientRect().left-view.position().left};
|
|
21909
|
+
}
|
|
21910
|
+
}
|
|
21911
|
+
epubLocation=window.PapyrusEpubReader.location(location,spineItems.length,epubViewMode==='single'?'paged':'chapter-scroll',pageGeometry);
|
|
21912
|
+
if(epubLocation){
|
|
21913
|
+
epubLocation.cfi=epubResizeAnchor?.cfi() || epubLocation.cfi;
|
|
21914
|
+
if(book.locations?.length?.()>0)epubLocation.progress=book.locations.percentageFromCfi(epubLocation.cfi);
|
|
21915
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
21916
|
+
}
|
|
21808
21917
|
const nextPage = index + 1;
|
|
21809
21918
|
if (nextPage === currentPage) return;
|
|
21810
21919
|
currentPage = nextPage;
|
|
@@ -21812,21 +21921,23 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21812
21921
|
});
|
|
21813
21922
|
}
|
|
21814
21923
|
|
|
21924
|
+
applyEpubZoom();
|
|
21815
21925
|
sendEpubDiagnostic('epub.display.start', diagnosticPayload);
|
|
21816
21926
|
await withEpubStageTimeout(
|
|
21817
|
-
|
|
21927
|
+
rendition.display(target || spineItems[0]?.href),
|
|
21818
21928
|
'rendition.display',
|
|
21819
21929
|
diagnosticPayload,
|
|
21820
21930
|
);
|
|
21821
21931
|
if (!isCurrentLoad()) throw new Error('EPUB load superseded by a newer load');
|
|
21822
21932
|
sendEpubDiagnostic('epub.display.end', diagnosticPayload);
|
|
21933
|
+
const resizeRendition=rendition;
|
|
21934
|
+
epubResizeAnchor=window.PapyrusEpubReader.installResizeAnchor(resizeRendition.manager,()=>resizeRendition.location?.start?.cfi);
|
|
21823
21935
|
if (
|
|
21824
21936
|
rendition &&
|
|
21825
21937
|
rendition.manager &&
|
|
21826
21938
|
typeof rendition.manager.on === 'function' &&
|
|
21827
21939
|
typeof rendition.on === 'function'
|
|
21828
21940
|
) {
|
|
21829
|
-
let touchStart = null;
|
|
21830
21941
|
let lastScrollOffset = -1;
|
|
21831
21942
|
const manager = rendition.manager;
|
|
21832
21943
|
epubScrollDiagnostics = createEpubScrollDiagnostics(manager);
|
|
@@ -21901,57 +22012,19 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21901
22012
|
return result;
|
|
21902
22013
|
};
|
|
21903
22014
|
}
|
|
21904
|
-
const
|
|
21905
|
-
const touch =
|
|
21906
|
-
(event && event.changedTouches && event.changedTouches[0]) ||
|
|
21907
|
-
(event && event.touches && event.touches[0]);
|
|
21908
|
-
if (!touch) return null;
|
|
21909
|
-
const x = Number(touch.screenX ?? touch.clientX);
|
|
21910
|
-
const y = Number(touch.screenY ?? touch.clientY);
|
|
21911
|
-
return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
|
|
21912
|
-
};
|
|
21913
|
-
const handleScroll = (event) => {
|
|
22015
|
+
const handleScroll = event => {
|
|
21914
22016
|
const offsetY = Math.max(0, Number(event && event.top) || 0);
|
|
21915
22017
|
epubScrollDiagnostics && epubScrollDiagnostics.scroll(event);
|
|
21916
|
-
if (Math.abs(offsetY
|
|
21917
|
-
lastScrollOffset
|
|
21918
|
-
sendEvent('VIEWER_SCROLL',
|
|
22018
|
+
if (Math.abs(offsetY-lastScrollOffset)<1) return;
|
|
22019
|
+
lastScrollOffset=offsetY;
|
|
22020
|
+
sendEvent('VIEWER_SCROLL',{offsetY});
|
|
21919
22021
|
};
|
|
21920
|
-
const handleTouchStart = (event) => {
|
|
21921
|
-
touchStart = event?.touches?.length > 1 ? null : getTouchPoint(event);
|
|
21922
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchStart(event);
|
|
21923
|
-
};
|
|
21924
|
-
const handleTouchMove = (event) => {
|
|
21925
|
-
if (event?.touches?.length > 1) touchStart = null;
|
|
21926
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchMove(event);
|
|
21927
|
-
};
|
|
21928
|
-
const handleTouchEnd = (event) => {
|
|
21929
|
-
const end = getTouchPoint(event);
|
|
21930
|
-
const start = touchStart;
|
|
21931
|
-
touchStart = null;
|
|
21932
|
-
const selectedText = event?.target?.ownerDocument?.defaultView?.getSelection?.()?.toString().trim() || '';
|
|
21933
|
-
if (!selectedText && start && end && epubViewMode === 'single' && Math.abs(end.x-start.x) >= 48 && Math.abs(end.x-start.x) > Math.abs(end.y-start.y)*1.5) {
|
|
21934
|
-
const active = rendition;
|
|
21935
|
-
const interactionSession = documentSessionId;
|
|
21936
|
-
epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
|
|
21937
|
-
if (active !== rendition || interactionSession !== documentSessionId) return;
|
|
21938
|
-
return end.x < start.x ? active.next() : active.prev();
|
|
21939
|
-
});
|
|
21940
|
-
epubNavigationQueue.catch(error => sendEvent('EPUB_NAVIGATION_ERROR', {message:String(error)}));
|
|
21941
|
-
} else if (!selectedText && start && end && Math.hypot(end.x - start.x, end.y - start.y) <= 12) {
|
|
21942
|
-
sendEvent('VIEWER_TAP', {});
|
|
21943
|
-
}
|
|
21944
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchEnd(event);
|
|
21945
|
-
};
|
|
21946
|
-
|
|
21947
22022
|
manager.on('scroll', handleScroll);
|
|
21948
22023
|
const handleScrolled = (event) => {
|
|
21949
22024
|
epubScrollDiagnostics && epubScrollDiagnostics.settled(event);
|
|
21950
22025
|
};
|
|
21951
22026
|
manager.on('scrolled', handleScrolled);
|
|
21952
|
-
|
|
21953
|
-
rendition.on('touchmove', handleTouchMove);
|
|
21954
|
-
rendition.on('touchend', handleTouchEnd);
|
|
22027
|
+
|
|
21955
22028
|
epubInteractionCleanup = () => {
|
|
21956
22029
|
epubSelectionCleanups.forEach((cleanup) => cleanup());
|
|
21957
22030
|
epubSelectionCleanups.clear();
|
|
@@ -21960,16 +22033,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21960
22033
|
if (originalEnqueue) queue.enqueue = originalEnqueue;
|
|
21961
22034
|
if (typeof manager.off === 'function') manager.off('scroll', handleScroll);
|
|
21962
22035
|
if (typeof manager.off === 'function') manager.off('scrolled', handleScrolled);
|
|
21963
|
-
if (typeof rendition.off === 'function') {
|
|
21964
|
-
rendition.off('touchstart', handleTouchStart);
|
|
21965
|
-
rendition.off('touchmove', handleTouchMove);
|
|
21966
|
-
rendition.off('touchend', handleTouchEnd);
|
|
21967
|
-
}
|
|
21968
22036
|
epubScrollDiagnostics = null;
|
|
21969
22037
|
};
|
|
21970
22038
|
}
|
|
21971
|
-
applyEpubZoom();
|
|
21972
|
-
|
|
21973
22039
|
const outline = await withEpubStageTimeout(
|
|
21974
22040
|
buildOutline(),
|
|
21975
22041
|
'outline',
|
|
@@ -21999,6 +22065,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21999
22065
|
const request = ++epubNavigationRequest;
|
|
22000
22066
|
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22001
22067
|
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22068
|
+
epubResizeAnchor?.invalidate();
|
|
22002
22069
|
await activeRendition.display(target);
|
|
22003
22070
|
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22004
22071
|
currentPage = pageIndex + 1;
|
|
@@ -22107,7 +22174,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22107
22174
|
};
|
|
22108
22175
|
|
|
22109
22176
|
let nativeMenuSelection = null;
|
|
22110
|
-
let epubViewMode = "
|
|
22177
|
+
let epubViewMode = "single";
|
|
22178
|
+
let epubLocation = null;
|
|
22111
22179
|
|
|
22112
22180
|
const handleCommand = async (message) => {
|
|
22113
22181
|
const { id, kind, payload } = message;
|
|
@@ -22120,7 +22188,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22120
22188
|
epubAnnotations = [];
|
|
22121
22189
|
annotationDocumentId = undefined;
|
|
22122
22190
|
zoom = 1.0;
|
|
22123
|
-
epubViewMode = "continuous";
|
|
22191
|
+
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22192
|
+
epubLocation = null;
|
|
22193
|
+
nativeMenuSelection = null;
|
|
22124
22194
|
epubNavigationRequest += 1;
|
|
22125
22195
|
epubNavigationQueue = Promise.resolve();
|
|
22126
22196
|
|
|
@@ -22185,6 +22255,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22185
22255
|
epubNavigationRequest += 1;
|
|
22186
22256
|
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22187
22257
|
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22258
|
+
epubResizeAnchor?.invalidate();
|
|
22188
22259
|
await activeRendition.display(annotation.anchor.href);
|
|
22189
22260
|
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22190
22261
|
const contents = activeRendition.getContents().find(c => spineItems[c.sectionIndex]?.href === annotation.anchor.href);
|
|
@@ -22226,6 +22297,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22226
22297
|
const active = rendition;
|
|
22227
22298
|
epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
|
|
22228
22299
|
if (active !== rendition || payload.documentSessionId !== documentSessionId) return;
|
|
22300
|
+
epubResizeAnchor?.invalidate();
|
|
22229
22301
|
return payload.direction < 0 ? active.prev() : active.next();
|
|
22230
22302
|
});
|
|
22231
22303
|
await epubNavigationQueue;
|
|
@@ -22234,25 +22306,40 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22234
22306
|
|
|
22235
22307
|
if (kind === 'set-epub-view-mode') {
|
|
22236
22308
|
if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB layout session');
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
sendResponse(id,true,null);
|
|
22309
|
+
const next=payload.epubMode ? (payload.epubMode==='paged'?'single':'continuous') : (payload.viewMode==='single'?'single':'continuous');
|
|
22310
|
+
{
|
|
22311
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22312
|
+
if(payload.documentSessionId!==documentSessionId || next===epubViewMode)return;
|
|
22313
|
+
const target=epubResizeAnchor?.cfi() || epubLocation?.cfi;
|
|
22314
|
+
epubViewMode=next;
|
|
22315
|
+
await renderEpubRendition('layout',epubLoadGeneration,target);
|
|
22316
|
+
});
|
|
22317
|
+
await epubNavigationQueue;
|
|
22318
|
+
}
|
|
22319
|
+
sendResponse(id,true,null);return;
|
|
22320
|
+
}
|
|
22321
|
+
if(kind === 'epub-go-to-location'){
|
|
22322
|
+
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22323
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>{if(payload.documentSessionId!==documentSessionId)return;epubResizeAnchor?.invalidate();return rendition.display(payload.cfi);});
|
|
22324
|
+
await epubNavigationQueue;sendResponse(id,true,null);return;
|
|
22248
22325
|
}
|
|
22249
22326
|
|
|
22250
22327
|
if (kind === 'set-zoom') {
|
|
22251
|
-
|
|
22252
|
-
|
|
22253
|
-
|
|
22254
|
-
|
|
22255
|
-
|
|
22328
|
+
const requestedZoom=Math.max(0.5,Math.min(4.0,payload.zoom || 1.0));
|
|
22329
|
+
if(currentType === 'epub') {
|
|
22330
|
+
const session=documentSessionId;
|
|
22331
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22332
|
+
if(session!==documentSessionId)return;
|
|
22333
|
+
const active=rendition;
|
|
22334
|
+
const cfi=epubResizeAnchor?.cfi() || epubLocation?.cfi;
|
|
22335
|
+
zoom=requestedZoom;applyEpubZoom();
|
|
22336
|
+
// Let the content CSS update before redisplaying the logical anchor.
|
|
22337
|
+
await new Promise(resolve=>(window.requestAnimationFrame || (callback=>setTimeout(callback,0)))(resolve));
|
|
22338
|
+
if(cfi && active===rendition && session===documentSessionId)await active.display(cfi);
|
|
22339
|
+
});
|
|
22340
|
+
await epubNavigationQueue;
|
|
22341
|
+
} else {zoom=requestedZoom;applyZoom();}
|
|
22342
|
+
sendState();sendResponse(id,true,{zoom});return;
|
|
22256
22343
|
}
|
|
22257
22344
|
|
|
22258
22345
|
if (kind === 'set-rotation') {
|