@papyrus-sdk/ui-react-native 0.2.35-beta.10 → 0.2.35-beta.11.epub.1
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 +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +476 -229
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +489 -241
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
- package/runtime/epubAnnotations.js +7 -4
- package/runtime/epubAnnotations.test.ts +6 -2
- package/runtime/epubReader.js +33 -0
- package/runtime/epubReader.test.ts +22 -0
- package/runtime/epubRuntime.test.ts +45 -0
- package/runtime/index.html +180 -79
- package/runtime/runtime.js +180 -79
- package/runtime/syncComicRuntime.mjs +6 -3
package/runtime/index.html
CHANGED
|
@@ -20483,6 +20483,42 @@ 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){
|
|
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 fraction=total?Math.max(0,(visualPage-1)/total):0;
|
|
20504
|
+
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:Boolean(raw.atStart),atEnd:Boolean(raw.atEnd)};
|
|
20505
|
+
}
|
|
20506
|
+
function install(contents,config){
|
|
20507
|
+
var doc=contents.document,win=contents.window,start=null,blocked=false;
|
|
20508
|
+
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;}
|
|
20509
|
+
function selected(){return Boolean(String(win.getSelection()||'').trim()) || config.blocked();}
|
|
20510
|
+
function interactive(target){return Boolean(target && target.closest && target.closest('a,button,input,textarea,select,[contenteditable="true"],[data-papyrus-overlay]'));}
|
|
20511
|
+
function begin(e){start=point(e);blocked=e.touches.length!==1 || selected() || interactive(e.target);}
|
|
20512
|
+
function move(e){if(e.touches.length!==1)blocked=true;}
|
|
20513
|
+
function end(e){var action=gesture(start,point(e),{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);}
|
|
20514
|
+
function cancel(){start=null;blocked=true;}
|
|
20515
|
+
doc.addEventListener('touchstart',begin,{passive:true});doc.addEventListener('touchmove',move,{passive:true});doc.addEventListener('touchend',end,{passive:true});doc.addEventListener('touchcancel',cancel,{passive:true});
|
|
20516
|
+
return function(){doc.removeEventListener('touchstart',begin);doc.removeEventListener('touchmove',move);doc.removeEventListener('touchend',end);doc.removeEventListener('touchcancel',cancel);};
|
|
20517
|
+
}
|
|
20518
|
+
root.PapyrusEpubReader={mode:mode,validCfi:validCfi,options:options,gesture:gesture,location:location,install:install};
|
|
20519
|
+
})(typeof window==='undefined'?globalThis:window);
|
|
20520
|
+
|
|
20521
|
+
/* @papyrus-epub-reader:end */
|
|
20486
20522
|
/* @papyrus-epub-annotations:start */
|
|
20487
20523
|
(function (root, factory) {
|
|
20488
20524
|
if (typeof module === 'object' && module.exports) module.exports = factory();
|
|
@@ -20561,6 +20597,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20561
20597
|
var color = /^#[0-9a-f]{6}$/i.test(annotation.color) ? annotation.color : '#FFC928';
|
|
20562
20598
|
var style = annotation.markupStyle || annotation.type;
|
|
20563
20599
|
var opacity = Number.isFinite(annotation.opacity) ? Math.max(0,Math.min(1,annotation.opacity)) : 0.35;
|
|
20600
|
+
if(style === 'highlight')opacity=Math.min(0.35,opacity);
|
|
20564
20601
|
rects.forEach(function(rect) {
|
|
20565
20602
|
var mark = doc.createElement('div');
|
|
20566
20603
|
var bodyRect=doc.body.getBoundingClientRect();
|
|
@@ -20573,8 +20610,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20573
20610
|
if (hasNote) {
|
|
20574
20611
|
var last = rects[rects.length-1], button = doc.createElement('button');
|
|
20575
20612
|
button.textContent = '●'; button.setAttribute('aria-label',options.labels().comment || '');
|
|
20576
|
-
|
|
20577
|
-
var
|
|
20613
|
+
var pageWidth=Math.max(44, options.pageWidth ? options.pageWidth() : win.innerWidth);
|
|
20614
|
+
var bodyRect=doc.body.getBoundingClientRect(), column=Math.max(0,Math.floor((last.left-bodyRect.left)/pageWidth));
|
|
20615
|
+
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';
|
|
20616
|
+
var key = column+":"+Math.floor(last.top/44);
|
|
20578
20617
|
var neighbors=noteGroups.get(key);
|
|
20579
20618
|
if(!neighbors){neighbors={button:button,ids:[]};noteGroups.set(key,neighbors);group.appendChild(button);}
|
|
20580
20619
|
neighbors.ids.push(annotation.id);
|
|
@@ -20595,10 +20634,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
20595
20634
|
doc.addEventListener('click',tapMarkup);
|
|
20596
20635
|
var observer = typeof win.ResizeObserver === 'function' ? new win.ResizeObserver(schedule) : null;
|
|
20597
20636
|
if (observer) observer.observe(doc.body);
|
|
20598
|
-
win.addEventListener('resize',schedule); doc.addEventListener('load',schedule,true);
|
|
20637
|
+
win.addEventListener('resize',schedule);win.addEventListener('scroll',schedule); doc.addEventListener('load',schedule,true);
|
|
20599
20638
|
if (doc.fonts && doc.fonts.ready) doc.fonts.ready.then(schedule);
|
|
20600
20639
|
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();}};
|
|
20640
|
+
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
20641
|
}
|
|
20603
20642
|
return {validAnchor:validAnchor,recoverRange:recoverRange,resolveRange:resolveRange,selection:selection,install:install};
|
|
20604
20643
|
});
|
|
@@ -21679,26 +21718,55 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21679
21718
|
pageCount,
|
|
21680
21719
|
});
|
|
21681
21720
|
|
|
21721
|
+
if (book.locations?.generate) {
|
|
21722
|
+
const activeBook=book;
|
|
21723
|
+
activeBook.locations.generate(150).then(() => {
|
|
21724
|
+
if (isCurrentLoad() && activeBook===book && epubLocation) {
|
|
21725
|
+
epubLocation.progress=activeBook.locations.percentageFromCfi(epubLocation.cfi);
|
|
21726
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
21727
|
+
}
|
|
21728
|
+
}).catch(() => {});
|
|
21729
|
+
}
|
|
21730
|
+
return renderEpubRendition(loadId,generation,null);
|
|
21731
|
+
};
|
|
21732
|
+
|
|
21733
|
+
const renderEpubRendition = async (loadId,generation,target) => {
|
|
21734
|
+
const diagnosticPayload={loadId};
|
|
21735
|
+
const isCurrentLoad=()=>generation===epubLoadGeneration;
|
|
21736
|
+
if(epubInteractionCleanup)epubInteractionCleanup();
|
|
21737
|
+
if(rendition)rendition.destroy();
|
|
21682
21738
|
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
|
-
});
|
|
21739
|
+
rendition = book.renderTo(viewer, window.PapyrusEpubReader.options(epubViewMode === 'single' ? 'paged' : 'chapter-scroll'));
|
|
21691
21740
|
sendEpubDiagnostic('epub.rendition.created', diagnosticPayload);
|
|
21692
21741
|
|
|
21693
21742
|
if (rendition && rendition.hooks && rendition.hooks.content) {
|
|
21694
21743
|
const session = documentSessionId;
|
|
21695
21744
|
const activeRendition = rendition;
|
|
21696
21745
|
rendition.hooks.content.register((contents) => {
|
|
21746
|
+
const removeGestureListeners = window.PapyrusEpubReader.install(contents, {
|
|
21747
|
+
mode: () => epubViewMode === 'single' ? 'paged' : 'chapter-scroll',
|
|
21748
|
+
rtl: () => book.package?.metadata?.direction === 'rtl' || book.spine?.direction === 'rtl',
|
|
21749
|
+
blocked: () => Boolean(nativeMenuSelection && String(nativeMenuSelection.contents?.window?.getSelection() || '').trim()),
|
|
21750
|
+
annotationHit: point => epubAnnotationRenderers.get(contents)?.hit(point.x,point.y),
|
|
21751
|
+
current: () => session === documentSessionId && activeRendition === rendition,
|
|
21752
|
+
tap: () => sendEvent('EPUB_CONTENT_TAP',{documentSessionId:session}),
|
|
21753
|
+
turn: direction => {
|
|
21754
|
+
epubNavigationQueue = epubNavigationQueue.catch(()=>{}).then(() => {
|
|
21755
|
+
if(session !== documentSessionId || activeRendition !== rendition)return;
|
|
21756
|
+
return direction<0?activeRendition.prev():activeRendition.next();
|
|
21757
|
+
});
|
|
21758
|
+
epubNavigationQueue.catch(error => sendEvent('EPUB_NAVIGATION_ERROR',{message:String(error)}));
|
|
21759
|
+
},
|
|
21760
|
+
});
|
|
21761
|
+
const gestureCleanup = () => {removeGestureListeners();epubSelectionCleanups.delete(gestureCleanup);};
|
|
21762
|
+
epubSelectionCleanups.add(gestureCleanup);
|
|
21763
|
+
contents.__papyrusGestureCleanup=gestureCleanup;
|
|
21697
21764
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21698
21765
|
if (href && window.PapyrusEpubAnnotations) {
|
|
21699
21766
|
const renderer = window.PapyrusEpubAnnotations.install(contents, {
|
|
21700
21767
|
href, get documentId() { return annotationDocumentId; },
|
|
21701
21768
|
isCurrent: () => session === documentSessionId && activeRendition === rendition,
|
|
21769
|
+
pageWidth: () => activeRendition.layout?.width || viewer.clientWidth,
|
|
21702
21770
|
annotations: () => epubAnnotations, labels: () => annotationLabels,
|
|
21703
21771
|
onTap: (id, ids) => sendEvent("EPUB_ANNOTATION_TAP", {documentSessionId: session, id, ids}),
|
|
21704
21772
|
});
|
|
@@ -21717,8 +21785,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21717
21785
|
typeof selectionWindow.getSelection === 'function'
|
|
21718
21786
|
) {
|
|
21719
21787
|
let selectionTimer = null;
|
|
21720
|
-
|
|
21721
|
-
let lastSelectionAt = 0;
|
|
21788
|
+
|
|
21722
21789
|
const reportSelection = () => {
|
|
21723
21790
|
selectionTimer = null;
|
|
21724
21791
|
if (session !== documentSessionId || activeRendition !== rendition) return;
|
|
@@ -21733,11 +21800,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21733
21800
|
try { cfi = contents.cfiFromRange(range); } catch (_) { return; }
|
|
21734
21801
|
const anchor = window.PapyrusEpubAnnotations?.selection(contents, cfi, href, annotationDocumentId);
|
|
21735
21802
|
if (!anchor) return;
|
|
21736
|
-
|
|
21737
|
-
const now = Date.now();
|
|
21738
|
-
if (key === lastSelectionKey && now - lastSelectionAt < 750) return;
|
|
21739
|
-
lastSelectionKey = key;
|
|
21740
|
-
lastSelectionAt = now;
|
|
21803
|
+
if (nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21741
21804
|
const payload = {documentSessionId: session, text: anchor.quote,
|
|
21742
21805
|
pageIndex: contents.sectionIndex + 1, anchor};
|
|
21743
21806
|
nativeMenuSelection = {contents, payload};
|
|
@@ -21752,6 +21815,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21752
21815
|
// The content document still emits selectionchange, so resolve its
|
|
21753
21816
|
// live Range to a CFI before the native menu action can fire.
|
|
21754
21817
|
if (text) reportSelection();
|
|
21818
|
+
else if (nativeMenuSelection?.contents === contents) nativeMenuSelection = null;
|
|
21755
21819
|
};
|
|
21756
21820
|
selectionDocument.addEventListener('selectionchange', handleSelectionChange);
|
|
21757
21821
|
const selectionCleanup = () => {
|
|
@@ -21774,6 +21838,7 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21774
21838
|
typeof rendition.hooks.unloaded.register === 'function'
|
|
21775
21839
|
) {
|
|
21776
21840
|
rendition.hooks.unloaded.register((view) => {
|
|
21841
|
+
view?.contents?.__papyrusGestureCleanup?.();
|
|
21777
21842
|
const cleanup = view && view.contents && view.contents.__papyrusSelectionCleanup;
|
|
21778
21843
|
if (typeof cleanup === 'function') cleanup();
|
|
21779
21844
|
const renderer = epubAnnotationRenderers.get(view?.contents);
|
|
@@ -21789,21 +21854,27 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21789
21854
|
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
21790
21855
|
const href = spineItems[contents.sectionIndex]?.href;
|
|
21791
21856
|
const anchor = href && window.PapyrusEpubAnnotations?.selection(contents,cfiRange,href,annotationDocumentId);
|
|
21792
|
-
if (!anchor) return;
|
|
21857
|
+
if (!anchor || nativeMenuSelection?.payload?.anchor?.cfiRange === anchor.cfiRange && nativeMenuSelection?.payload?.anchor?.quote === anchor.quote) return;
|
|
21793
21858
|
epubScrollDiagnostics && epubScrollDiagnostics.setSelectionActive(true);
|
|
21794
21859
|
const payload = {documentSessionId: selectionSession, text: anchor.quote, pageIndex: contents.sectionIndex+1, anchor};
|
|
21795
21860
|
nativeMenuSelection = {contents, payload};
|
|
21796
21861
|
sendEvent('EPUB_TEXT_SELECTED', payload);
|
|
21797
21862
|
});
|
|
21798
|
-
['rendered','resized','layout'].forEach(name => rendition.on(name, () => {
|
|
21863
|
+
['rendered','resized','layout','relocated'].forEach(name => rendition.on(name, () => {
|
|
21799
21864
|
if (selectionSession === documentSessionId && selectionRendition === rendition) epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
21800
21865
|
}));
|
|
21801
21866
|
rendition.on('relocated', (location) => {
|
|
21867
|
+
if (selectionSession !== documentSessionId || selectionRendition !== rendition) return;
|
|
21802
21868
|
const start = location && location.start;
|
|
21803
21869
|
let index = start && Number.isInteger(start.index) ? start.index : -1;
|
|
21804
21870
|
if (index < 0 && start && start.href) index = getSpineIndexByHref(start.href);
|
|
21805
21871
|
if (index < 0 || index >= spineItems.length) return;
|
|
21806
21872
|
epubScrollDiagnostics && epubScrollDiagnostics.relocated(location);
|
|
21873
|
+
epubLocation=window.PapyrusEpubReader.location(location,spineItems.length,epubViewMode==='single'?'paged':'chapter-scroll');
|
|
21874
|
+
if(epubLocation){
|
|
21875
|
+
if(book.locations?.length?.()>0)epubLocation.progress=book.locations.percentageFromCfi(epubLocation.cfi);
|
|
21876
|
+
sendEvent('EPUB_LOCATION',{documentSessionId,location:epubLocation});
|
|
21877
|
+
}
|
|
21807
21878
|
const nextPage = index + 1;
|
|
21808
21879
|
if (nextPage === currentPage) return;
|
|
21809
21880
|
currentPage = nextPage;
|
|
@@ -21811,9 +21882,10 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21811
21882
|
});
|
|
21812
21883
|
}
|
|
21813
21884
|
|
|
21885
|
+
applyEpubZoom();
|
|
21814
21886
|
sendEpubDiagnostic('epub.display.start', diagnosticPayload);
|
|
21815
21887
|
await withEpubStageTimeout(
|
|
21816
|
-
|
|
21888
|
+
rendition.display(target || spineItems[0]?.href),
|
|
21817
21889
|
'rendition.display',
|
|
21818
21890
|
diagnosticPayload,
|
|
21819
21891
|
);
|
|
@@ -21825,7 +21897,6 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21825
21897
|
typeof rendition.manager.on === 'function' &&
|
|
21826
21898
|
typeof rendition.on === 'function'
|
|
21827
21899
|
) {
|
|
21828
|
-
let touchStart = null;
|
|
21829
21900
|
let lastScrollOffset = -1;
|
|
21830
21901
|
const manager = rendition.manager;
|
|
21831
21902
|
epubScrollDiagnostics = createEpubScrollDiagnostics(manager);
|
|
@@ -21900,48 +21971,19 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21900
21971
|
return result;
|
|
21901
21972
|
};
|
|
21902
21973
|
}
|
|
21903
|
-
const
|
|
21904
|
-
const touch =
|
|
21905
|
-
(event && event.changedTouches && event.changedTouches[0]) ||
|
|
21906
|
-
(event && event.touches && event.touches[0]);
|
|
21907
|
-
if (!touch) return null;
|
|
21908
|
-
const x = Number(touch.screenX ?? touch.clientX);
|
|
21909
|
-
const y = Number(touch.screenY ?? touch.clientY);
|
|
21910
|
-
return Number.isFinite(x) && Number.isFinite(y) ? { x, y } : null;
|
|
21911
|
-
};
|
|
21912
|
-
const handleScroll = (event) => {
|
|
21974
|
+
const handleScroll = event => {
|
|
21913
21975
|
const offsetY = Math.max(0, Number(event && event.top) || 0);
|
|
21914
21976
|
epubScrollDiagnostics && epubScrollDiagnostics.scroll(event);
|
|
21915
|
-
if (Math.abs(offsetY
|
|
21916
|
-
lastScrollOffset
|
|
21917
|
-
sendEvent('VIEWER_SCROLL',
|
|
21918
|
-
};
|
|
21919
|
-
const handleTouchStart = (event) => {
|
|
21920
|
-
touchStart = getTouchPoint(event);
|
|
21921
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchStart(event);
|
|
21922
|
-
};
|
|
21923
|
-
const handleTouchMove = (event) => {
|
|
21924
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchMove(event);
|
|
21925
|
-
};
|
|
21926
|
-
const handleTouchEnd = (event) => {
|
|
21927
|
-
const end = getTouchPoint(event);
|
|
21928
|
-
const start = touchStart;
|
|
21929
|
-
touchStart = null;
|
|
21930
|
-
const selectedText = event?.target?.ownerDocument?.defaultView?.getSelection?.()?.toString().trim() || '';
|
|
21931
|
-
if (!selectedText && start && end && Math.hypot(end.x - start.x, end.y - start.y) <= 12) {
|
|
21932
|
-
sendEvent('VIEWER_TAP', {});
|
|
21933
|
-
}
|
|
21934
|
-
epubScrollDiagnostics && epubScrollDiagnostics.touchEnd(event);
|
|
21977
|
+
if (Math.abs(offsetY-lastScrollOffset)<1) return;
|
|
21978
|
+
lastScrollOffset=offsetY;
|
|
21979
|
+
sendEvent('VIEWER_SCROLL',{offsetY});
|
|
21935
21980
|
};
|
|
21936
|
-
|
|
21937
21981
|
manager.on('scroll', handleScroll);
|
|
21938
21982
|
const handleScrolled = (event) => {
|
|
21939
21983
|
epubScrollDiagnostics && epubScrollDiagnostics.settled(event);
|
|
21940
21984
|
};
|
|
21941
21985
|
manager.on('scrolled', handleScrolled);
|
|
21942
|
-
|
|
21943
|
-
rendition.on('touchmove', handleTouchMove);
|
|
21944
|
-
rendition.on('touchend', handleTouchEnd);
|
|
21986
|
+
|
|
21945
21987
|
epubInteractionCleanup = () => {
|
|
21946
21988
|
epubSelectionCleanups.forEach((cleanup) => cleanup());
|
|
21947
21989
|
epubSelectionCleanups.clear();
|
|
@@ -21950,16 +21992,9 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21950
21992
|
if (originalEnqueue) queue.enqueue = originalEnqueue;
|
|
21951
21993
|
if (typeof manager.off === 'function') manager.off('scroll', handleScroll);
|
|
21952
21994
|
if (typeof manager.off === 'function') manager.off('scrolled', handleScrolled);
|
|
21953
|
-
if (typeof rendition.off === 'function') {
|
|
21954
|
-
rendition.off('touchstart', handleTouchStart);
|
|
21955
|
-
rendition.off('touchmove', handleTouchMove);
|
|
21956
|
-
rendition.off('touchend', handleTouchEnd);
|
|
21957
|
-
}
|
|
21958
21995
|
epubScrollDiagnostics = null;
|
|
21959
21996
|
};
|
|
21960
21997
|
}
|
|
21961
|
-
applyEpubZoom();
|
|
21962
|
-
|
|
21963
21998
|
const outline = await withEpubStageTimeout(
|
|
21964
21999
|
buildOutline(),
|
|
21965
22000
|
'outline',
|
|
@@ -21973,6 +22008,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21973
22008
|
return { pageCount, outline };
|
|
21974
22009
|
};
|
|
21975
22010
|
|
|
22011
|
+
let epubNavigationQueue = Promise.resolve();
|
|
22012
|
+
let epubNavigationRequest = 0;
|
|
21976
22013
|
const displayEpubPage = async (pageIndex) => {
|
|
21977
22014
|
if (!rendition) return;
|
|
21978
22015
|
const item = spineItems[pageIndex];
|
|
@@ -21982,9 +22019,18 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
21982
22019
|
target,
|
|
21983
22020
|
pageIndex,
|
|
21984
22021
|
});
|
|
21985
|
-
|
|
21986
|
-
|
|
21987
|
-
|
|
22022
|
+
const activeRendition = rendition;
|
|
22023
|
+
const session = documentSessionId;
|
|
22024
|
+
const request = ++epubNavigationRequest;
|
|
22025
|
+
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22026
|
+
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22027
|
+
await activeRendition.display(target);
|
|
22028
|
+
if (request !== epubNavigationRequest || session !== documentSessionId || activeRendition !== rendition) return;
|
|
22029
|
+
currentPage = pageIndex + 1;
|
|
22030
|
+
sendState();
|
|
22031
|
+
});
|
|
22032
|
+
epubNavigationQueue = navigation;
|
|
22033
|
+
await navigation;
|
|
21988
22034
|
};
|
|
21989
22035
|
|
|
21990
22036
|
const getTextContent = async (pageIndex) => {
|
|
@@ -22086,6 +22132,8 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22086
22132
|
};
|
|
22087
22133
|
|
|
22088
22134
|
let nativeMenuSelection = null;
|
|
22135
|
+
let epubViewMode = "single";
|
|
22136
|
+
let epubLocation = null;
|
|
22089
22137
|
|
|
22090
22138
|
const handleCommand = async (message) => {
|
|
22091
22139
|
const { id, kind, payload } = message;
|
|
@@ -22098,6 +22146,11 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22098
22146
|
epubAnnotations = [];
|
|
22099
22147
|
annotationDocumentId = undefined;
|
|
22100
22148
|
zoom = 1.0;
|
|
22149
|
+
epubViewMode = payload.epubMode === "chapter-scroll" ? "continuous" : "single";
|
|
22150
|
+
epubLocation = null;
|
|
22151
|
+
nativeMenuSelection = null;
|
|
22152
|
+
epubNavigationRequest += 1;
|
|
22153
|
+
epubNavigationQueue = Promise.resolve();
|
|
22101
22154
|
|
|
22102
22155
|
if (currentType === 'text') {
|
|
22103
22156
|
const result = await loadText(
|
|
@@ -22152,17 +22205,23 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22152
22205
|
epubAnnotationRenderers.forEach(renderer => renderer.schedule());
|
|
22153
22206
|
} else {
|
|
22154
22207
|
const annotation = epubAnnotations.find(a => a.id === payload.annotationId);
|
|
22155
|
-
if (!annotation) throw new Error('Annotation not available');
|
|
22208
|
+
if (!annotation || (annotation.anchor.documentId && annotation.anchor.documentId !== annotationDocumentId)) throw new Error('Annotation not available for this document');
|
|
22156
22209
|
// Navigation uses the CFI, never a synthetic percentage/page rectangle.
|
|
22157
22210
|
const navigationSession = documentSessionId;
|
|
22158
22211
|
const activeRendition = rendition;
|
|
22159
22212
|
// Open the confirmed chapter first, resolve its quote, then navigate its actual range.
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22213
|
+
epubNavigationRequest += 1;
|
|
22214
|
+
const navigation = epubNavigationQueue.catch(() => {}).then(async () => {
|
|
22215
|
+
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22216
|
+
await activeRendition.display(annotation.anchor.href);
|
|
22217
|
+
if(navigationSession !== documentSessionId || activeRendition !== rendition)throw new Error('Stale EPUB navigation');
|
|
22218
|
+
const contents = activeRendition.getContents().find(c => spineItems[c.sectionIndex]?.href === annotation.anchor.href);
|
|
22219
|
+
const range = contents && window.PapyrusEpubAnnotations.resolveRange(contents,annotation.anchor);
|
|
22220
|
+
if(!range)throw new Error('EPUB anchor unresolved');
|
|
22221
|
+
await activeRendition.display(contents.cfiFromRange(range));
|
|
22222
|
+
});
|
|
22223
|
+
epubNavigationQueue = navigation;
|
|
22224
|
+
await navigation;
|
|
22166
22225
|
}
|
|
22167
22226
|
sendResponse(id,true,null); return;
|
|
22168
22227
|
}
|
|
@@ -22189,12 +22248,54 @@ https://github.com/nodeca/pako/blob/main/LICENSE
|
|
|
22189
22248
|
return;
|
|
22190
22249
|
}
|
|
22191
22250
|
|
|
22251
|
+
if (kind === 'epub-turn-page') {
|
|
22252
|
+
if (epubViewMode !== 'single') {sendResponse(id,true,null); return;}
|
|
22253
|
+
if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB navigation');
|
|
22254
|
+
const active = rendition;
|
|
22255
|
+
epubNavigationQueue = epubNavigationQueue.catch(() => {}).then(() => {
|
|
22256
|
+
if (active !== rendition || payload.documentSessionId !== documentSessionId) return;
|
|
22257
|
+
return payload.direction < 0 ? active.prev() : active.next();
|
|
22258
|
+
});
|
|
22259
|
+
await epubNavigationQueue;
|
|
22260
|
+
sendResponse(id,true,null); return;
|
|
22261
|
+
}
|
|
22262
|
+
|
|
22263
|
+
if (kind === 'set-epub-view-mode') {
|
|
22264
|
+
if (currentType !== 'epub' || payload.documentSessionId !== documentSessionId) throw new Error('Stale EPUB layout session');
|
|
22265
|
+
const next=payload.epubMode ? (payload.epubMode==='paged'?'single':'continuous') : (payload.viewMode==='single'?'single':'continuous');
|
|
22266
|
+
{
|
|
22267
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22268
|
+
if(payload.documentSessionId!==documentSessionId || next===epubViewMode)return;
|
|
22269
|
+
const target=epubLocation?.cfi;
|
|
22270
|
+
epubViewMode=next;
|
|
22271
|
+
await renderEpubRendition('layout',epubLoadGeneration,target);
|
|
22272
|
+
});
|
|
22273
|
+
await epubNavigationQueue;
|
|
22274
|
+
}
|
|
22275
|
+
sendResponse(id,true,null);return;
|
|
22276
|
+
}
|
|
22277
|
+
if(kind === 'epub-go-to-location'){
|
|
22278
|
+
if(currentType!=='epub' || payload.documentSessionId!==documentSessionId || !window.PapyrusEpubReader.validCfi(payload.cfi))throw new Error('Invalid EPUB location');
|
|
22279
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(()=>payload.documentSessionId===documentSessionId?rendition.display(payload.cfi):undefined);
|
|
22280
|
+
await epubNavigationQueue;sendResponse(id,true,null);return;
|
|
22281
|
+
}
|
|
22282
|
+
|
|
22192
22283
|
if (kind === 'set-zoom') {
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22197
|
-
|
|
22284
|
+
const requestedZoom=Math.max(0.5,Math.min(4.0,payload.zoom || 1.0));
|
|
22285
|
+
if(currentType === 'epub') {
|
|
22286
|
+
const session=documentSessionId;
|
|
22287
|
+
epubNavigationQueue=epubNavigationQueue.catch(()=>{}).then(async()=>{
|
|
22288
|
+
if(session!==documentSessionId)return;
|
|
22289
|
+
const active=rendition;
|
|
22290
|
+
const cfi=epubLocation?.cfi;
|
|
22291
|
+
zoom=requestedZoom;applyEpubZoom();
|
|
22292
|
+
// Let the content CSS update before redisplaying the logical anchor.
|
|
22293
|
+
await new Promise(resolve=>(window.requestAnimationFrame || (callback=>setTimeout(callback,0)))(resolve));
|
|
22294
|
+
if(cfi && active===rendition && session===documentSessionId)await active.display(cfi);
|
|
22295
|
+
});
|
|
22296
|
+
await epubNavigationQueue;
|
|
22297
|
+
} else {zoom=requestedZoom;applyZoom();}
|
|
22298
|
+
sendState();sendResponse(id,true,{zoom});return;
|
|
22198
22299
|
}
|
|
22199
22300
|
|
|
22200
22301
|
if (kind === 'set-rotation') {
|