@readium/navigator 2.10.3 → 2.11.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/dist/audio/AudioNavigator.js +1 -1
- package/dist/audio/AudioPoolManager.js +1 -1
- package/dist/audio/engine/WebAudioEngine.js +1 -1
- package/dist/divina/DivinaNavigator.js +1 -0
- package/dist/divina/DivinaPageManager.js +1 -0
- package/dist/divina/DivinaPagedPresenter.js +1 -0
- package/dist/divina/DivinaPeripherals.js +1 -0
- package/dist/divina/DivinaScrolledPresenter.js +1 -0
- package/dist/divina/DivinaSpreader.js +1 -0
- package/dist/divina/DivinaVariantSelector.js +1 -0
- package/dist/divina/preferences/DivinaDefaults.js +1 -0
- package/dist/divina/preferences/DivinaPreferences.js +1 -0
- package/dist/divina/preferences/DivinaPreferencesEditor.js +1 -0
- package/dist/divina/preferences/DivinaSettings.js +1 -0
- package/dist/divina/protection/DivinaNavigatorProtector.js +1 -0
- package/dist/epub/EpubNavigator.js +1 -1
- package/dist/epub/frame/FrameBlobBuilder.js +3 -1
- package/dist/epub/frame/FrameComms.js +1 -1
- package/dist/epub/frame/FrameManager.js +1 -1
- package/dist/epub/frame/FramePoolManager.js +1 -1
- package/dist/epub/fxl/FXLFrameManager.js +1 -1
- package/dist/epub/fxl/FXLFramePoolManager.js +1 -1
- package/dist/epub/fxl/FXLPeripherals.js +2 -2
- package/dist/helpers/serialize.js +1 -0
- package/dist/index.js +1 -1
- package/dist/peripherals/KeyboardConditionBridge.js +1 -1
- package/dist/peripherals/KeyboardPeripherals.js +1 -1
- package/dist/webpub/WebPubFrameManager.js +1 -1
- package/dist/webpub/WebPubFramePoolManager.js +1 -1
- package/dist/webpub/WebPubNavigator.js +1 -1
- package/package.json +5 -5
- package/src/audio/AudioNavigator.ts +107 -5
- package/src/audio/AudioPoolManager.ts +14 -8
- package/src/audio/engine/AudioEngine.ts +34 -1
- package/src/audio/engine/WebAudioEngine.ts +48 -3
- package/src/divina/DivinaNavigator.ts +704 -0
- package/src/divina/DivinaPageManager.ts +322 -0
- package/src/divina/DivinaPagedPresenter.ts +508 -0
- package/src/divina/DivinaPeripherals.ts +630 -0
- package/src/divina/DivinaScrolledPresenter.ts +516 -0
- package/src/divina/DivinaSpreader.ts +202 -0
- package/src/divina/DivinaVariantSelector.ts +77 -0
- package/src/divina/index.ts +8 -0
- package/src/divina/preferences/DivinaDefaults.ts +37 -0
- package/src/divina/preferences/DivinaPreferences.ts +77 -0
- package/src/divina/preferences/DivinaPreferencesEditor.ts +96 -0
- package/src/divina/preferences/DivinaSettings.ts +38 -0
- package/src/divina/preferences/index.ts +4 -0
- package/src/divina/protection/DivinaNavigatorProtector.ts +44 -0
- package/src/epub/EpubNavigator.ts +73 -7
- package/src/epub/frame/FrameBlobBuilder.ts +144 -39
- package/src/epub/frame/FrameComms.ts +42 -7
- package/src/epub/frame/FrameManager.ts +27 -16
- package/src/epub/frame/FramePoolManager.ts +106 -48
- package/src/epub/fxl/FXLFrameManager.ts +99 -34
- package/src/epub/fxl/FXLFramePoolManager.ts +98 -53
- package/src/epub/fxl/FXLPeripherals.ts +22 -1
- package/src/helpers/serialize.ts +9 -0
- package/src/index.ts +1 -0
- package/src/peripherals/KeyboardConditionBridge.ts +15 -5
- package/src/peripherals/KeyboardPeripherals.ts +13 -7
- package/src/webpub/WebPubFrameManager.ts +27 -16
- package/src/webpub/WebPubFramePoolManager.ts +5 -2
- package/src/webpub/WebPubNavigator.ts +44 -0
- package/types/src/audio/AudioNavigator.d.ts +29 -0
- package/types/src/audio/engine/AudioEngine.d.ts +27 -1
- package/types/src/audio/engine/WebAudioEngine.d.ts +14 -2
- package/types/src/divina/DivinaNavigator.d.ts +119 -0
- package/types/src/divina/DivinaPageManager.d.ts +66 -0
- package/types/src/divina/DivinaPagedPresenter.d.ts +122 -0
- package/types/src/divina/DivinaPeripherals.d.ts +121 -0
- package/types/src/divina/DivinaScrolledPresenter.d.ts +125 -0
- package/types/src/divina/DivinaSpreader.d.ts +65 -0
- package/types/src/divina/DivinaVariantSelector.d.ts +30 -0
- package/types/src/divina/index.d.ts +8 -0
- package/types/src/divina/preferences/DivinaDefaults.d.ts +18 -0
- package/types/src/divina/preferences/DivinaPreferences.d.ts +33 -0
- package/types/src/divina/preferences/DivinaPreferencesEditor.d.ts +20 -0
- package/types/src/divina/preferences/DivinaSettings.d.ts +26 -0
- package/types/src/divina/preferences/index.d.ts +4 -0
- package/types/src/divina/protection/DivinaNavigatorProtector.d.ts +14 -0
- package/types/src/epub/EpubNavigator.d.ts +7 -1
- package/types/src/epub/frame/FrameBlobBuilder.d.ts +19 -3
- package/types/src/epub/frame/FrameComms.d.ts +8 -1
- package/types/src/epub/frame/FrameManager.d.ts +3 -0
- package/types/src/epub/frame/FramePoolManager.d.ts +5 -1
- package/types/src/epub/fxl/FXLFrameManager.d.ts +7 -0
- package/types/src/epub/fxl/FXLFramePoolManager.d.ts +8 -2
- package/types/src/epub/fxl/FXLPeripherals.d.ts +3 -0
- package/types/src/helpers/serialize.d.ts +1 -0
- package/types/src/index.d.ts +1 -0
- package/types/src/peripherals/KeyboardPeripherals.d.ts +1 -0
- package/types/src/webpub/WebPubFrameManager.d.ts +3 -0
- package/types/src/webpub/WebPubNavigator.d.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Locator as p,LocatorLocations as c,getTime as g}from"@readium/shared";import{MediaNavigator as E}from"../Navigator.js";import{AudioPoolManager as P}from"./AudioPoolManager.js";import{AudioNavigatorProtector as L}from"./protection/AudioNavigatorProtector.js";import{NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as k}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as w,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as _}from"../peripherals/KeyboardPeripherals.js";import{AudioPreferences as T}from"./preferences/AudioPreferences.js";import{AudioDefaults as S}from"./preferences/AudioDefaults.js";import{AudioSettings as y}from"./preferences/AudioSettings.js";import{WebAudioEngine as b}from"./engine/WebAudioEngine.js";import{AudioPreferencesEditor as v}from"./preferences/AudioPreferencesEditor.js";const I=n=>({trackLoaded:n.trackLoaded??(()=>{}),positionChanged:n.positionChanged??(()=>{}),timelineItemChanged:n.timelineItemChanged??(()=>{}),error:n.error??(()=>{}),trackEnded:n.trackEnded??(()=>{}),play:n.play??(()=>{}),pause:n.pause??(()=>{}),metadataLoaded:n.metadataLoaded??(()=>{}),stalled:n.stalled??(()=>{}),seeking:n.seeking??(()=>{}),seekable:n.seekable??(()=>{}),contentProtection:n.contentProtection??(()=>{}),peripheral:n.peripheral??(()=>{}),contextMenu:n.contextMenu??(()=>{}),remotePlaybackStateChanged:n.remotePlaybackStateChanged??(()=>{})});class B extends E{constructor(t,e,i,s={preferences:{},defaults:{}}){if(super(),this.positionPollInterval=null,this.navigationId=0,this._playIntent=!1,this._preferencesEditor=null,this._mediaSessionEnabled=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._isNavigating=!1,this._isStalled=!1,this._stalledWatchdog=null,this._stalledCheckTime=0,this.pub=t,this.listeners=I(e),this._preferences=new T(s.preferences),this._defaults=new S(s.defaults),this._settings=new y(this._preferences,this._defaults),t.readingOrder.items.length===0)throw new Error("AudioNavigator: publication has an empty reading order");if(i)this.currentLocation=this.ensureLocatorLocations(i);else{const l=this.pub.readingOrder.items[0];this.currentLocation=new p({href:l.href,type:l.type||"audio/mpeg",title:l.title,locations:new c({position:1,progression:0,totalProgression:0,fragments:["t=0"]})})}const o=this.currentLocation.href.split("#")[0],r=this.hrefToTrackIndex(o);if(r===-1)throw new Error(`AudioNavigator: initial href "${o}" not found in reading order`);const h=g(this.currentLocation.locations)||0,d=new b({playback:{state:{currentTime:h,duration:0},playWhenReady:!1,index:r}});this.pool=new P(d,t,s.contentProtection);const a=s.contentProtection||{};this._contentProtection=a;const u=this.mergeKeyboardPeripherals(a,s.keyboardPeripherals||[]);(a.disableContextMenu||a.checkAutomation||a.checkIFrameEmbedding||a.monitorDevTools||a.protectPrinting?.disable||a.disableDragAndDrop||a.protectCopy)&&(this._navigatorProtector=new L(a),this._suspiciousActivityListener=l=>{const{type:f,...m}=l.detail;f==="context_menu"?this.listeners.contextMenu(m):this.listeners.contentProtection(f,m)},window.addEventListener(k,this._suspiciousActivityListener)),u.length>0&&(this._keyboardPeripheralsManager=new w({keyboardPeripherals:u}),this._keyboardPeripheralListener=l=>{this.listeners.peripheral(l.detail)},window.addEventListener(_,this._keyboardPeripheralListener)),this.setupEventListeners(),this._isNavigating=!0,this.pool.setCurrentAudio(r,"forward"),this.applyPreferences(),this.waitForLoadedAndSeeked(h).then(()=>{this._isNavigating=!1,this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement()),this._notifyTimelineChange(this.currentLocator),this.listeners.positionChanged(this.currentLocator),this._setupRemotePlayback()}).catch(()=>{this._isNavigating=!1})}get settings(){return this._settings}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new v(this._preferences,this.settings)),this._preferencesEditor}async submitPreferences(t){this._preferences=this._preferences.merging(t),this.applyPreferences()}applyPreferences(){this._settings=new y(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new v(this._preferences,this.settings)),this.pool.audioEngine.setVolume(this._settings.volume),this.pool.audioEngine.setPlaybackRate(this._settings.playbackRate,this._settings.preservePitch),this.positionPollInterval!==null&&this.startPositionPolling(),this._settings.enableMediaSession&&!this._mediaSessionEnabled?(this._mediaSessionEnabled=!0,this.setupMediaSession()):!this._settings.enableMediaSession&&this._mediaSessionEnabled&&(this._mediaSessionEnabled=!1,this.destroyMediaSession())}get publication(){return this.pub}get timeline(){return this.pub.timeline}_notifyTimelineChange(t){const e=this.pub.timeline.locate(t);e!==this._currentTimelineItem&&(this._currentTimelineItem=e,this.listeners.timelineItemChanged(e),this._settings.enableMediaSession&&this.updateMediaSessionMetadata())}ensureLocatorLocations(t){return new p({...t,locations:t.locations instanceof c?t.locations:t.locations?new c(t.locations):void 0})}hrefToTrackIndex(t){const e=t.split("#")[0];return this.pub.readingOrder.items.findIndex(i=>i.href===e)}currentTrackIndex(){return this.hrefToTrackIndex(this.currentLocation.href)}get currentLocator(){return this.currentLocation}get isPlaying(){return this.pool.audioEngine.isPlaying()}get isPaused(){return this.pool.audioEngine.isPaused()}get duration(){return this.pool.audioEngine.duration()}get currentTime(){return this.pool.audioEngine.currentTime()}createLocator(t,e){const i=this.pub.readingOrder.items[t];if(!i)throw new Error(`Invalid track index: ${t}`);const s=this.pool.audioEngine.duration();return new p({href:i.href,type:i.type||"audio/mpeg",title:i.title,locations:new c({progression:s>0?e/s:0,position:t+1,fragments:[`t=${e}`]})})}waitForLoadedAndSeeked(t,e){return new Promise((i,s)=>{const o=()=>{if(e!==void 0&&e!==this.navigationId){i();return}if(t<=0){i();return}const d=()=>{this.pool.audioEngine.off("seeked",d),i()};this.pool.audioEngine.on("seeked",d),this.seek(t)};if(this.pool.audioEngine.isLoaded()){o();return}const r=()=>{this.pool.audioEngine.off("canplaythrough",r),this.pool.audioEngine.off("error",h),o()},h=d=>{this.pool.audioEngine.off("canplaythrough",r),this.pool.audioEngine.off("error",h),s(d)};this.pool.audioEngine.on("canplaythrough",r),this.pool.audioEngine.on("error",h)})}setupEventListeners(){this.pool.audioEngine.on("error",t=>{this.listeners.error(t,this.currentLocator)}),this.pool.audioEngine.on("ended",async()=>{this.stopPositionPolling(),this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:1,fragments:[`t=${this.duration}`]})),this.listeners.trackEnded(this.currentLocator),this.canGoForward&&(await this.nextTrack(),this._settings.autoPlay&&this.play())}),this.pool.audioEngine.on("play",()=>{this._isNavigating||(this.startPositionPolling(),this.listeners.play(this.currentLocator))}),this.pool.audioEngine.on("playing",()=>{this._isNavigating||this._setStalled(!1)}),this.pool.audioEngine.on("pause",()=>{this._isNavigating||(this.stopPositionPolling(),this.listeners.pause(this.currentLocator))}),this.pool.audioEngine.on("seeked",()=>{if(this._isNavigating)return;this.listeners.seeking(!1);const t=this.currentTime,e=this.duration,i=e>0?t/e:0;this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:i,fragments:[`t=${t}`]})),this._notifyTimelineChange(this.currentLocation),this.listeners.positionChanged(this.currentLocation)}),this.pool.audioEngine.on("seeking",()=>{this._isNavigating||this.listeners.seeking(!0)}),this.pool.audioEngine.on("waiting",()=>{this._isNavigating||this.listeners.seeking(!0)}),this.pool.audioEngine.on("stalled",()=>{this._isNavigating||this._setStalled(!0)}),this.pool.audioEngine.on("canplaythrough",()=>{this._isNavigating||this._setStalled(!1)}),this.pool.audioEngine.on("progress",t=>{this._isNavigating||this.listeners.seekable(t)}),this.pool.audioEngine.on("loadedmetadata",()=>{const t=this.pool.audioEngine.getMediaElement(),e={duration:this.pool.audioEngine.duration(),textTracks:t.textTracks,readyState:t.readyState,networkState:t.networkState};this.listeners.metadataLoaded(e)})}_setStalled(t){this._isStalled!==t&&(this._isStalled=t,this.listeners.stalled(t),t?(this._stalledCheckTime=this.currentTime,this._startStalledWatchdog()):this._stopStalledWatchdog())}_startStalledWatchdog(){this._stalledWatchdog=setInterval(()=>{if(!this.isPlaying){this._setStalled(!1);return}const t=this.currentTime;t!==this._stalledCheckTime&&this._setStalled(!1),this._stalledCheckTime=t},500)}_stopStalledWatchdog(){this._stalledWatchdog!==null&&(clearInterval(this._stalledWatchdog),this._stalledWatchdog=null)}setupMediaSession(){"mediaSession"in navigator&&(navigator.mediaSession.setActionHandler("play",()=>this.play()),navigator.mediaSession.setActionHandler("pause",()=>this.pause()),navigator.mediaSession.setActionHandler("previoustrack",()=>this.goBackward(!1,()=>{})),navigator.mediaSession.setActionHandler("nexttrack",()=>this.goForward(!1,()=>{})),navigator.mediaSession.setActionHandler("seekbackward",t=>this.jump(-(t.seekOffset||10))),navigator.mediaSession.setActionHandler("seekforward",t=>this.jump(t.seekOffset||10)),this.updateMediaSessionMetadata())}updateMediaSessionMetadata(){if(!("mediaSession"in navigator))return;const t=this.currentTrackIndex(),e=this.pub.readingOrder.items[t],i=this.pub.getCover();navigator.mediaSession.metadata=new MediaMetadata({title:e?.title||`Track ${t+1}`,artist:this.pub.metadata.authors?this.pub.metadata.authors.items.map(s=>s.name.getTranslation()).join(", "):void 0,album:this.pub.metadata.title.getTranslation(),artwork:i?[{src:i.toURL(this.pub.baseURL)??i.href,type:i.type}]:void 0})}startPositionPolling(){this.stopPositionPolling(),this.positionPollInterval=setInterval(()=>{const t=this.currentTime,e=this.duration,i=e>0?t/e:0;this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:i,fragments:[`t=${t}`]})),this._notifyTimelineChange(this.currentLocation),this.listeners.positionChanged(this.currentLocation)},this._settings.pollInterval)}stopPositionPolling(){this.positionPollInterval!==null&&(clearInterval(this.positionPollInterval),this.positionPollInterval=null)}async go(t,e,i){try{t=this.ensureLocatorLocations(t);const s=t.href.split("#")[0],o=this.hrefToTrackIndex(s),r=g(t.locations)||0;if(o===-1){i(!1);return}const h=++this.navigationId,d=this.currentTrackIndex(),a=o>=d?"forward":"backward",u=this.isPlaying||this._playIntent;if(this._playIntent=u,this._isNavigating=!0,this.stopPositionPolling(),this.pool.setCurrentAudio(o,a),this.currentLocation=t.copyWithLocations(t.locations),await this.waitForLoadedAndSeeked(r,h),this._isNavigating=!1,h!==this.navigationId){i(!1);return}o!==d&&this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement()),this._notifyTimelineChange(this.currentLocator),this.listeners.positionChanged(this.currentLocator),this._settings.enableMediaSession&&this.updateMediaSessionMetadata(),u&&this.play(),i(!0)}catch(s){this._isNavigating=!1,console.error("Failed to go to locator:",s),i(!1)}finally{this._playIntent=!1}}async goLink(t,e,i){const s=this.hrefToTrackIndex(t.href);if(s===-1){i(!1);return}const o=g(t.locator.locations)??0,r=this.createLocator(s,o);await this.go(r,e,i)}async goForward(t,e){if(!this.canGoForward){e(!1);return}await this.nextTrack(),e(!0)}async goBackward(t,e){if(!this.canGoBackward){e(!1);return}await this.previousTrack(),e(!0)}play(){this.pool.audioEngine.play()}pause(){this.pool.audioEngine.pause()}stop(){this.pool.audioEngine.stop()}async nextTrack(){if(!this.canGoForward)return;const t=this.createLocator(this.currentTrackIndex()+1,0);await this.go(t,!1,()=>{})}async previousTrack(){if(!this.canGoBackward)return;const t=this.createLocator(this.currentTrackIndex()-1,0);await this.go(t,!1,()=>{})}seek(t){this.pool.audioEngine.skip(t-this.pool.audioEngine.currentTime())}jump(t){this.pool.audioEngine.skip(t)}skipForward(){this.pool.audioEngine.skip(this._settings.skipForwardInterval)}skipBackward(){this.pool.audioEngine.skip(-this._settings.skipBackwardInterval)}get isTrackStart(){return this.currentTrackIndex()===0&&(g(this.currentLocation.locations)||0)===0}get isTrackEnd(){const t=this.currentTrackIndex();if(t!==this.pub.readingOrder.items.length-1)return!1;const e=this.currentLocation.locations?.progression;if(e!==void 0)return e>=1;const i=this.pub.readingOrder.items[t],s=this.duration||i?.duration||0;return s>0&&(g(this.currentLocation.locations)??0)>=s}get canGoBackward(){return this.currentTrackIndex()>0}get canGoForward(){return this.currentTrackIndex()<this.pub.readingOrder.items.length-1}get remotePlayback(){const t=this.pool.audioEngine.getMediaElement();return"remote"in t?t.remote:void 0}_setupRemotePlayback(){if(this._contentProtection.disableRemotePlayback)return;const t=this.remotePlayback;t&&(t.onconnecting=()=>this.listeners.remotePlaybackStateChanged("connecting"),t.onconnect=()=>this.listeners.remotePlaybackStateChanged("connected"),t.ondisconnect=()=>this.listeners.remotePlaybackStateChanged("disconnected"))}destroyMediaSession(){"mediaSession"in navigator&&(navigator.mediaSession.metadata=null,navigator.mediaSession.setActionHandler("play",null),navigator.mediaSession.setActionHandler("pause",null),navigator.mediaSession.setActionHandler("previoustrack",null),navigator.mediaSession.setActionHandler("nexttrack",null),navigator.mediaSession.setActionHandler("seekbackward",null),navigator.mediaSession.setActionHandler("seekforward",null))}destroy(){this.stopPositionPolling(),this._stopStalledWatchdog(),this.destroyMediaSession(),this._suspiciousActivityListener&&window.removeEventListener(k,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(_,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),this.pool.destroy()}}export{B as AudioNavigator};
|
|
1
|
+
import{Locator as f,LocatorLocations as c,getTime as p}from"@readium/shared";import{MediaNavigator as E}from"../Navigator.js";import{AudioPoolManager as P}from"./AudioPoolManager.js";import{AudioNavigatorProtector as w}from"./protection/AudioNavigatorProtector.js";import{NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as _}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as T,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as y}from"../peripherals/KeyboardPeripherals.js";import{AudioPreferences as S}from"./preferences/AudioPreferences.js";import{AudioDefaults as b}from"./preferences/AudioDefaults.js";import{AudioSettings as v}from"./preferences/AudioSettings.js";import{WebAudioEngine as I}from"./engine/WebAudioEngine.js";import{AudioPreferencesEditor as L}from"./preferences/AudioPreferencesEditor.js";const x=r=>({trackLoaded:r.trackLoaded??(()=>{}),positionChanged:r.positionChanged??(()=>{}),timelineItemChanged:r.timelineItemChanged??(()=>{}),error:r.error??(()=>{}),trackEnded:r.trackEnded??(()=>{}),play:r.play??(()=>{}),pause:r.pause??(()=>{}),metadataLoaded:r.metadataLoaded??(()=>{}),stalled:r.stalled??(()=>{}),seeking:r.seeking??(()=>{}),seekable:r.seekable??(()=>{}),contentProtection:r.contentProtection??(()=>{}),peripheral:r.peripheral??(()=>{}),contextMenu:r.contextMenu??(()=>{}),remotePlaybackStateChanged:r.remotePlaybackStateChanged??(()=>{})});class $ extends E{constructor(t,e,i,s={preferences:{},defaults:{}}){if(super(),this.positionPollInterval=null,this.navigationId=0,this._playIntent=!1,this._preferencesEditor=null,this._mediaSessionEnabled=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._isNavigating=!1,this._isStalled=!1,this._destroyed=!1,this._stalledWatchdog=null,this._stalledCheckTime=0,this.pub=t,this.listeners=x(e),this._preferences=new S(s.preferences),this._defaults=new b(s.defaults),this._settings=new v(this._preferences,this._defaults),t.readingOrder.items.length===0)throw new Error("AudioNavigator: publication has an empty reading order");if(i)this.currentLocation=this.ensureLocatorLocations(i);else{const l=this.pub.readingOrder.items[0];this.currentLocation=new f({href:l.href,type:l.type||"audio/mpeg",title:l.title,locations:new c({position:1,progression:0,totalProgression:0,fragments:["t=0"]})})}const o=this.currentLocation.href.split("#")[0];let h=this.hrefToTrackIndex(o);if(h===-1){const l=this.currentLocation.locations?.totalProgression;if(l!==void 0){const g=this.locatorFromTotalProgression(l);this.currentLocation=g.locator,h=g.trackIndex}else throw new Error(`AudioNavigator: initial href "${o}" not found in reading order`)}const d=p(this.currentLocation.locations)||0,a=new I({playback:{state:{currentTime:d,duration:0},playWhenReady:!1,index:h},mseLoaderFactory:s.mseLoaderFactory});this.pool=new P(a,t,s.contentProtection);const n=s.contentProtection||{};this._contentProtection=n;const u=this.mergeKeyboardPeripherals(n,s.keyboardPeripherals||[]);(n.disableContextMenu||n.checkAutomation||n.checkIFrameEmbedding||n.monitorDevTools||n.protectPrinting?.disable||n.disableDragAndDrop||n.protectCopy)&&(this._navigatorProtector=new w(n),this._suspiciousActivityListener=l=>{const{type:g,...k}=l.detail;g==="context_menu"?this.listeners.contextMenu(k):this.listeners.contentProtection(g,k)},window.addEventListener(_,this._suspiciousActivityListener)),u.length>0&&(this._keyboardPeripheralsManager=new T({keyboardPeripherals:u}),this._keyboardPeripheralListener=l=>{this.listeners.peripheral(l.detail)},window.addEventListener(y,this._keyboardPeripheralListener)),this.setupEventListeners(),this._isNavigating=!0;const m=()=>this.startInitialLoad(h,d);if(s.mediaElementSetup){if(this._destroyed)return;Promise.resolve().then(()=>s.mediaElementSetup(this.pool.audioEngine.getMediaElement())).catch(l=>{this.listeners.error(l,this.currentLocator)}).then(m)}else m()}startInitialLoad(t,e){this._destroyed||(this.pool.setCurrentAudio(t,"forward"),this.applyPreferences(),this.waitForLoadedAndSeeked(e).then(()=>{this._isNavigating=!1,this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement()),this._notifyTimelineChange(this.currentLocator),this.listeners.positionChanged(this.currentLocator),this._setupRemotePlayback()}).catch(()=>{this._isNavigating=!1}))}get settings(){return this._settings}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new L(this._preferences,this.settings)),this._preferencesEditor}async submitPreferences(t){this._preferences=this._preferences.merging(t),this.applyPreferences()}applyPreferences(){this._settings=new v(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new L(this._preferences,this.settings)),this.pool.audioEngine.setVolume(this._settings.volume),this.pool.audioEngine.setPlaybackRate(this._settings.playbackRate,this._settings.preservePitch),this.positionPollInterval!==null&&this.startPositionPolling(),this._settings.enableMediaSession&&!this._mediaSessionEnabled?(this._mediaSessionEnabled=!0,this.setupMediaSession()):!this._settings.enableMediaSession&&this._mediaSessionEnabled&&(this._mediaSessionEnabled=!1,this.destroyMediaSession())}get publication(){return this.pub}get timeline(){return this.pub.timeline}_notifyTimelineChange(t){const e=this.pub.timeline.locate(t);e!==this._currentTimelineItem&&(this._currentTimelineItem=e,this.listeners.timelineItemChanged(e),this._settings.enableMediaSession&&this.updateMediaSessionMetadata())}ensureLocatorLocations(t){return new f({...t,locations:t.locations instanceof c?t.locations:t.locations?new c(t.locations):void 0})}hrefToTrackIndex(t){const e=t.split("#")[0];return this.pub.readingOrder.items.findIndex(i=>i.href===e)}currentTrackIndex(){return this.hrefToTrackIndex(this.currentLocation.href)}locatorFromTotalProgression(t){const e=this.pub.readingOrder.items,i=e.map(a=>a.duration??0),s=i.reduce((a,n)=>a+n,0);let o=0,h=0;if(s>0){let a=Math.min(Math.max(t,0),1)*s;for(let n=0;n<i.length;n++){if(o=n,a<=i[n]||n===i.length-1){h=a;break}a-=i[n]}}const d=e[o];return{trackIndex:o,locator:new f({href:d.href,type:d.type||"",title:d.title,locations:new c({position:o+1,progression:i[o]>0?h/i[o]:0,totalProgression:Math.min(Math.max(t,0),1),fragments:[`t=${h}`]})})}}get currentLocator(){return this.currentLocation}get isPlaying(){return this.pool.audioEngine.isPlaying()}get isPaused(){return this.pool.audioEngine.isPaused()}get duration(){return this.pool.audioEngine.duration()}get currentTime(){return this.pool.audioEngine.currentTime()}createLocator(t,e){const i=this.pub.readingOrder.items[t];if(!i)throw new Error(`Invalid track index: ${t}`);const s=this.pool.audioEngine.duration();return new f({href:i.href,type:i.type||"audio/mpeg",title:i.title,locations:new c({progression:s>0?e/s:0,position:t+1,fragments:[`t=${e}`]})})}waitForLoadedAndSeeked(t,e){return new Promise((i,s)=>{const o=()=>{if(e!==void 0&&e!==this.navigationId){i();return}if(t<=0){i();return}const a=()=>{this.pool.audioEngine.off("seeked",a),i()};this.pool.audioEngine.on("seeked",a),this.seek(t)};if(this.pool.audioEngine.isLoaded()){o();return}const h=()=>{this.pool.audioEngine.off("canplaythrough",h),this.pool.audioEngine.off("error",d),o()},d=a=>{this.pool.audioEngine.off("canplaythrough",h),this.pool.audioEngine.off("error",d),s(a)};this.pool.audioEngine.on("canplaythrough",h),this.pool.audioEngine.on("error",d)})}setupEventListeners(){this.pool.audioEngine.on("error",t=>{this.listeners.error(t,this.currentLocator)}),this.pool.audioEngine.on("ended",async()=>{if(this.stopPositionPolling(),this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:1,fragments:[`t=${this.duration}`]})),this.listeners.trackEnded(this.currentLocator),!this.canGoForward){this.listeners.positionChanged(this.currentLocator);return}await this.nextTrack(),this._settings.autoPlay&&this.play()}),this.pool.audioEngine.on("play",()=>{this._isNavigating||(this.startPositionPolling(),this.listeners.play(this.currentLocator))}),this.pool.audioEngine.on("playing",()=>{this._isNavigating||this._setStalled(!1)}),this.pool.audioEngine.on("pause",()=>{this._isNavigating||(this.stopPositionPolling(),this.listeners.pause(this.currentLocator))}),this.pool.audioEngine.on("seeked",()=>{if(this._isNavigating)return;this.listeners.seeking(!1);const t=this.currentTime,e=this.duration,i=e>0?t/e:0;this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:i,fragments:[`t=${t}`]})),this._notifyTimelineChange(this.currentLocation),this.listeners.positionChanged(this.currentLocation)}),this.pool.audioEngine.on("seeking",()=>{this._isNavigating||this.listeners.seeking(!0)}),this.pool.audioEngine.on("waiting",()=>{this._isNavigating||this.listeners.seeking(!0)}),this.pool.audioEngine.on("stalled",()=>{this._isNavigating||this._setStalled(!0)}),this.pool.audioEngine.on("canplaythrough",()=>{this._isNavigating||this._setStalled(!1)}),this.pool.audioEngine.on("progress",t=>{this._isNavigating||this.listeners.seekable(t)}),this.pool.audioEngine.on("loadedmetadata",()=>{const t=this.pool.audioEngine.getMediaElement(),e={duration:this.pool.audioEngine.duration(),textTracks:t.textTracks,readyState:t.readyState,networkState:t.networkState};this.listeners.metadataLoaded(e)})}_setStalled(t){this._isStalled!==t&&(this._isStalled=t,this.listeners.stalled(t),t?(this._stalledCheckTime=this.currentTime,this._startStalledWatchdog()):this._stopStalledWatchdog())}_startStalledWatchdog(){this._stalledWatchdog=setInterval(()=>{if(!this.isPlaying){this._setStalled(!1);return}const t=this.currentTime;t!==this._stalledCheckTime&&this._setStalled(!1),this._stalledCheckTime=t},500)}_stopStalledWatchdog(){this._stalledWatchdog!==null&&(clearInterval(this._stalledWatchdog),this._stalledWatchdog=null)}setupMediaSession(){"mediaSession"in navigator&&(navigator.mediaSession.setActionHandler("play",()=>this.play()),navigator.mediaSession.setActionHandler("pause",()=>this.pause()),navigator.mediaSession.setActionHandler("previoustrack",()=>this.goBackward(!1,()=>{})),navigator.mediaSession.setActionHandler("nexttrack",()=>this.goForward(!1,()=>{})),navigator.mediaSession.setActionHandler("seekbackward",t=>this.jump(-(t.seekOffset||10))),navigator.mediaSession.setActionHandler("seekforward",t=>this.jump(t.seekOffset||10)),this.updateMediaSessionMetadata())}updateMediaSessionMetadata(){if(!("mediaSession"in navigator))return;const t=this.currentTrackIndex(),e=this.pub.readingOrder.items[t],i=this.pub.getCover();navigator.mediaSession.metadata=new MediaMetadata({title:e?.title||`Track ${t+1}`,artist:this.pub.metadata.authors?this.pub.metadata.authors.items.map(s=>s.name.getTranslation()).join(", "):void 0,album:this.pub.metadata.title.getTranslation(),artwork:i?[{src:i.toURL(this.pub.baseURL)??i.href,type:i.type}]:void 0})}startPositionPolling(){this.stopPositionPolling(),this.positionPollInterval=setInterval(()=>{const t=this.currentTime,e=this.duration,i=e>0?t/e:0;this.currentLocation=this.currentLocation.copyWithLocations(new c({position:this.currentTrackIndex()+1,progression:i,fragments:[`t=${t}`]})),this._notifyTimelineChange(this.currentLocation),this.listeners.positionChanged(this.currentLocation)},this._settings.pollInterval)}stopPositionPolling(){this.positionPollInterval!==null&&(clearInterval(this.positionPollInterval),this.positionPollInterval=null)}async go(t,e,i){try{t=this.ensureLocatorLocations(t);const s=t.href.split("#")[0],o=this.hrefToTrackIndex(s),h=p(t.locations)||0;if(o===-1){i(!1);return}const d=++this.navigationId,a=this.currentTrackIndex(),n=o>=a?"forward":"backward",u=this.isPlaying||this._playIntent;if(this._playIntent=u,this._isNavigating=!0,this.stopPositionPolling(),this.pool.setCurrentAudio(o,n),this.currentLocation=t.copyWithLocations(t.locations),await this.waitForLoadedAndSeeked(h,d),this._isNavigating=!1,d!==this.navigationId){i(!1);return}o!==a&&this.listeners.trackLoaded(this.pool.audioEngine.getMediaElement()),this._notifyTimelineChange(this.currentLocator),this.listeners.positionChanged(this.currentLocator),this._settings.enableMediaSession&&this.updateMediaSessionMetadata(),u&&this.play(),i(!0)}catch(s){this._isNavigating=!1,console.error("Failed to go to locator:",s),i(!1)}finally{this._playIntent=!1}}async goLink(t,e,i){const s=this.hrefToTrackIndex(t.href);if(s===-1){i(!1);return}const o=p(t.locator.locations)??0,h=this.createLocator(s,o);await this.go(h,e,i)}async goForward(t,e){if(!this.canGoForward){e(!1);return}await this.nextTrack(),e(!0)}async goBackward(t,e){if(!this.canGoBackward){e(!1);return}await this.previousTrack(),e(!0)}play(){this.pool.audioEngine.play()}pause(){this.pool.audioEngine.pause()}stop(){this.pool.audioEngine.stop()}async nextTrack(){if(!this.canGoForward)return;const t=this.createLocator(this.currentTrackIndex()+1,0);await this.go(t,!1,()=>{})}async previousTrack(){if(!this.canGoBackward)return;const t=this.createLocator(this.currentTrackIndex()-1,0);await this.go(t,!1,()=>{})}seek(t){this.pool.audioEngine.skip(t-this.pool.audioEngine.currentTime())}jump(t){this.pool.audioEngine.skip(t)}skipForward(){this.pool.audioEngine.skip(this._settings.skipForwardInterval)}skipBackward(){this.pool.audioEngine.skip(-this._settings.skipBackwardInterval)}get isTrackStart(){return this.currentTrackIndex()===0&&(p(this.currentLocation.locations)||0)===0}get isTrackEnd(){const t=this.currentTrackIndex();if(t!==this.pub.readingOrder.items.length-1)return!1;const e=this.currentLocation.locations?.progression;if(e!==void 0)return e>=1;const i=this.pub.readingOrder.items[t],s=this.duration||i?.duration||0;return s>0&&(p(this.currentLocation.locations)??0)>=s}get canGoBackward(){return this.currentTrackIndex()>0}get canGoForward(){return this.currentTrackIndex()<this.pub.readingOrder.items.length-1}get remotePlayback(){const t=this.pool.audioEngine.getMediaElement();return"remote"in t?t.remote:void 0}_setupRemotePlayback(){if(this._contentProtection.disableRemotePlayback)return;const t=this.remotePlayback;t&&(t.onconnecting=()=>this.listeners.remotePlaybackStateChanged("connecting"),t.onconnect=()=>this.listeners.remotePlaybackStateChanged("connected"),t.ondisconnect=()=>this.listeners.remotePlaybackStateChanged("disconnected"))}destroyMediaSession(){"mediaSession"in navigator&&(navigator.mediaSession.metadata=null,navigator.mediaSession.setActionHandler("play",null),navigator.mediaSession.setActionHandler("pause",null),navigator.mediaSession.setActionHandler("previoustrack",null),navigator.mediaSession.setActionHandler("nexttrack",null),navigator.mediaSession.setActionHandler("seekbackward",null),navigator.mediaSession.setActionHandler("seekforward",null))}destroy(){this._destroyed=!0,this.stopPositionPolling(),this._stopStalledWatchdog(),this.destroyMediaSession(),this._suspiciousActivityListener&&window.removeEventListener(_,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(y,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),this.pool.destroy()}}export{$ as AudioNavigator};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class p{constructor(t,o,s={}){this.pool=new Map,this._audioEngine=t,this._publication=o,this._supportedAudioTypes=this.detectSupportedAudioTypes(),s.disableRemotePlayback&&(this._audioEngine.getMediaElement().disableRemotePlayback=!0)}detectSupportedAudioTypes(){const t=document.createElement("audio"),o=new Set;for(const e of this._publication.readingOrder.items){e.type&&o.add(e.type);for(const i of e.alternates?.items??[])i.type&&o.add(i.type)}const s=new Map;for(const e of o){const i=t.canPlayType(e);i!==""&&s.set(e,i)}return s}pickPlayableHref(t){const o=this._publication.baseURL,s=[t,...t.alternates?.items??[]];let e;for(const i of s){if(!i.type)continue;const n=this._supportedAudioTypes.get(i.type);if(!n)continue;const a=i.toURL(o)??i.href;if(n==="probably")return{href:a,type:i.type};e||(e={href:a,type:i.type,confidence:n})}return e?{href:e.href,type:e.type}:{href:t.toURL(o)??t.href,type:t.type}}get audioEngine(){return this._audioEngine}ensure(t){let o=this.pool.get(t);return o||(o=document.createElement("audio"),o.preload="auto",this._audioEngine.isWebAudioActive&&(o.crossOrigin="anonymous"),o.src=t,o.load(),this.pool.set(t,o)),o}update(t){if(this._audioEngine.usesMse)return;const o=this._publication.readingOrder.items,s=new Set;for(let e=0;e<o.length;e++){if(e===t)continue;const{href:i}=this.pickPlayableHref(o[e]);e>=t-1&&e<=t+1?(this.ensure(i),s.add(i)):e>=t-1&&e<=t+1&&this.pool.has(i)&&s.add(i)}for(const[e,i]of this.pool)s.has(e)||(i.removeAttribute("src"),i.load(),this.pool.delete(e))}setCurrentAudio(t,o){const{href:s,type:e}=this.pickPlayableHref(this._publication.readingOrder.items[t]);if(this.audioEngine.changeSrc(s,e),this.pool.has(s)){const i=this.pool.get(s);i.removeAttribute("src"),i.load(),this.pool.delete(s)}this.update(t)}destroy(){this.audioEngine.stop(),this.audioEngine.destroy();for(const[,t]of this.pool)t.removeAttribute("src"),t.load();this.pool.clear()}}export{p as AudioPoolManager};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PreservePitchWorklet as r}from"./PreservePitchWorklet.js";class u{constructor(e){this.audioContext=null,this.sourceNode=null,this.gainNode=null,this.listeners={},this.isMutedValue=!1,this.isPlayingValue=!1,this.isPausedValue=!1,this.isLoadingValue=!1,this.isLoadedValue=!1,this.isEndedValue=!1,this.isStoppedValue=!1,this.worklet=null,this.webAudioActive=!1,this.boundOnCanPlayThrough=this.onCanPlayThrough.bind(this),this.boundOnTimeUpdate=this.onTimeUpdate.bind(this),this.boundOnError=this.onError.bind(this),this.boundOnEnded=this.onEnded.bind(this),this.boundOnStalled=this.onStalled.bind(this),this.boundOnEmptied=this.onEmptied.bind(this),this.boundOnSuspend=this.onSuspend.bind(this),this.boundOnWaiting=this.onWaiting.bind(this),this.boundOnLoadedMetadata=this.onLoadedMetadata.bind(this),this.boundOnSeeking=this.onSeeking.bind(this),this.boundOnSeeked=this.onSeeked.bind(this),this.boundOnPlay=this.onPlay.bind(this),this.boundOnPlaying=this.onPlaying.bind(this),this.boundOnPause=this.onPause.bind(this),this.boundOnProgress=this.onProgress.bind(this),this.playback=e.playback,this.mediaElement=document.createElement("audio"),this.mediaElement.addEventListener("canplaythrough",this.boundOnCanPlayThrough),this.mediaElement.addEventListener("timeupdate",this.boundOnTimeUpdate),this.mediaElement.addEventListener("error",this.boundOnError),this.mediaElement.addEventListener("ended",this.boundOnEnded),this.mediaElement.addEventListener("stalled",this.boundOnStalled),this.mediaElement.addEventListener("emptied",this.boundOnEmptied),this.mediaElement.addEventListener("suspend",this.boundOnSuspend),this.mediaElement.addEventListener("waiting",this.boundOnWaiting),this.mediaElement.addEventListener("loadedmetadata",this.boundOnLoadedMetadata),this.mediaElement.addEventListener("seeking",this.boundOnSeeking),this.mediaElement.addEventListener("seeked",this.boundOnSeeked),this.mediaElement.addEventListener("play",this.boundOnPlay),this.mediaElement.addEventListener("playing",this.boundOnPlaying),this.mediaElement.addEventListener("pause",this.boundOnPause),this.mediaElement.addEventListener("progress",this.boundOnProgress),this.mediaElement.currentTime=this.playback.state.currentTime}on(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}off(e,t){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(i=>i!==t))}async ensureAudioContextRunning(){this.audioContext||(this.audioContext=new AudioContext),this.audioContext.state==="suspended"&&await this.audioContext.resume()}getOrCreateAudioContext(){return this.audioContext||(this.audioContext=new AudioContext),this.audioContext}onTimeUpdate(){this.emit("timeupdate",this.mediaElement.currentTime)}onCanPlayThrough(){this.isLoadingValue=!1,this.isLoadedValue=!0,this.emit("canplaythrough",null)}onError(){console.error("Error loading media element"),this.emit("error",this.mediaElement.error)}onEnded(){this.isPlayingValue=!1,this.isPausedValue=!1,this.isEndedValue=!0,this.emit("ended",null)}onStalled(e){this.emit("stalled",e)}onEmptied(e){this.emit("emptied",e)}onSuspend(e){this.emit("suspend",e)}onWaiting(e){this.emit("waiting",e)}onLoadedMetadata(e){this.emit("loadedmetadata",e)}onSeeking(e){this.emit("seeking",e)}onSeeked(e){this.emit("seeked",e)}onPlay(){this.emit("play",null)}onPlaying(){this.emit("playing",null)}onPause(){this.emit("pause",null)}onProgress(){this.emit("progress",this.mediaElement.seekable)}emit(e,t){this.listeners[e]&&this.listeners[e].forEach(i=>i(t))}async play(){if(!this.isPlayingValue)try{this.audioContext&&await this.ensureAudioContextRunning(),await this.mediaElement.play(),this.isPlayingValue=!0,this.isPausedValue=!1,this.isStoppedValue=!1}catch(e){if(e?.name==="AbortError")return;console.error("error trying to play media element",e),this.emit("error",e)}}pause(){this.mediaElement.pause(),this.isPlayingValue=!1,this.isPausedValue=!0}stop(){this.mediaElement.pause(),this.mediaElement.currentTime=0,this.isPlayingValue=!1,this.isPausedValue=!1,this.isStoppedValue=!0}setVolume(e){const t=Math.max(0,Math.min(1,e));this.gainNode?(this.mediaElement.volume=1,this.gainNode.gain.value=t):this.mediaElement.volume=t,this.isMutedValue=t===0}skip(e){const t=this.mediaElement.duration;if(!isFinite(t))return;const i=this.mediaElement.currentTime+e;i<0?this.mediaElement.currentTime=0:i>t?this.mediaElement.currentTime=t:this.mediaElement.currentTime=i}currentTime(){return this.mediaElement.currentTime}duration(){return this.mediaElement.duration}isPlaying(){return this.isPlayingValue}isPaused(){return this.isPausedValue}isStopped(){return this.isStoppedValue}isLoading(){return this.isLoadingValue}isLoaded(){return this.isLoadedValue}isEnded(){return this.isEndedValue}isMuted(){return this.isMutedValue}setPlaybackRate(e,t){this.mediaElement.playbackRate=e,t?"preservesPitch"in this.mediaElement?this.mediaElement.preservesPitch=!0:this.activateWebAudio().then(()=>{this.worklet?this.worklet.updatePitchFactor(1/e):r.createWorklet({ctx:this.getOrCreateAudioContext(),pitchFactor:1}).then(i=>{this.sourceNode&&this.sourceNode.disconnect(),this.worklet=i,this.sourceNode?.connect(this.worklet.workletNode),this.worklet.workletNode.connect(this.gainNode),this.worklet.updatePitchFactor(1/e)}).catch(i=>{console.warn("Failed to create preserve pitch worklet",i)})}).catch(i=>{console.warn("Web Audio unavailable, playing without pitch correction:",i)}):("preservesPitch"in this.mediaElement&&(this.mediaElement.preservesPitch=!1),this.worklet&&(this.worklet.destroy(),this.worklet=null,this.webAudioActive&&this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode.connect(this.gainNode))))}async activateWebAudio(){if(this.webAudioActive)return;const e=this.mediaElement.src;if(!e)return;const t=this.mediaElement.currentTime,i=this.isPlayingValue;i&&(this.mediaElement.pause(),this.isPlayingValue=!1),this.mediaElement.crossOrigin="anonymous",this.mediaElement.src=e,this.mediaElement.load();try{await new Promise((
|
|
1
|
+
import{PreservePitchWorklet as r}from"./PreservePitchWorklet.js";class u{constructor(e){this.audioContext=null,this.sourceNode=null,this.gainNode=null,this.listeners={},this.isMutedValue=!1,this.isPlayingValue=!1,this.isPausedValue=!1,this.isLoadingValue=!1,this.isLoadedValue=!1,this.isEndedValue=!1,this.isStoppedValue=!1,this.worklet=null,this.webAudioActive=!1,this.mseLoader=null,this.currentHref="",this.boundOnCanPlayThrough=this.onCanPlayThrough.bind(this),this.boundOnTimeUpdate=this.onTimeUpdate.bind(this),this.boundOnError=this.onError.bind(this),this.boundOnEnded=this.onEnded.bind(this),this.boundOnStalled=this.onStalled.bind(this),this.boundOnEmptied=this.onEmptied.bind(this),this.boundOnSuspend=this.onSuspend.bind(this),this.boundOnWaiting=this.onWaiting.bind(this),this.boundOnLoadedMetadata=this.onLoadedMetadata.bind(this),this.boundOnSeeking=this.onSeeking.bind(this),this.boundOnSeeked=this.onSeeked.bind(this),this.boundOnPlay=this.onPlay.bind(this),this.boundOnPlaying=this.onPlaying.bind(this),this.boundOnPause=this.onPause.bind(this),this.boundOnProgress=this.onProgress.bind(this),this.playback=e.playback,this.mseLoaderFactory=e.mseLoaderFactory??null,this.mediaElement=document.createElement("audio"),this.mediaElement.addEventListener("canplaythrough",this.boundOnCanPlayThrough),this.mediaElement.addEventListener("timeupdate",this.boundOnTimeUpdate),this.mediaElement.addEventListener("error",this.boundOnError),this.mediaElement.addEventListener("ended",this.boundOnEnded),this.mediaElement.addEventListener("stalled",this.boundOnStalled),this.mediaElement.addEventListener("emptied",this.boundOnEmptied),this.mediaElement.addEventListener("suspend",this.boundOnSuspend),this.mediaElement.addEventListener("waiting",this.boundOnWaiting),this.mediaElement.addEventListener("loadedmetadata",this.boundOnLoadedMetadata),this.mediaElement.addEventListener("seeking",this.boundOnSeeking),this.mediaElement.addEventListener("seeked",this.boundOnSeeked),this.mediaElement.addEventListener("play",this.boundOnPlay),this.mediaElement.addEventListener("playing",this.boundOnPlaying),this.mediaElement.addEventListener("pause",this.boundOnPause),this.mediaElement.addEventListener("progress",this.boundOnProgress),this.mediaElement.currentTime=this.playback.state.currentTime}on(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}off(e,t){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(i=>i!==t))}async ensureAudioContextRunning(){this.audioContext||(this.audioContext=new AudioContext),this.audioContext.state==="suspended"&&await this.audioContext.resume()}getOrCreateAudioContext(){return this.audioContext||(this.audioContext=new AudioContext),this.audioContext}onTimeUpdate(){this.emit("timeupdate",this.mediaElement.currentTime)}onCanPlayThrough(){this.isLoadingValue=!1,this.isLoadedValue=!0,this.emit("canplaythrough",null)}onError(){console.error("Error loading media element"),this.emit("error",this.mediaElement.error)}onEnded(){this.isPlayingValue=!1,this.isPausedValue=!1,this.isEndedValue=!0,this.emit("ended",null)}onStalled(e){this.emit("stalled",e)}onEmptied(e){this.emit("emptied",e)}onSuspend(e){this.emit("suspend",e)}onWaiting(e){this.emit("waiting",e)}onLoadedMetadata(e){this.emit("loadedmetadata",e)}onSeeking(e){this.emit("seeking",e)}onSeeked(e){this.emit("seeked",e)}onPlay(){this.emit("play",null)}onPlaying(){this.emit("playing",null)}onPause(){this.emit("pause",null)}onProgress(){this.emit("progress",this.mediaElement.seekable)}emit(e,t){this.listeners[e]&&this.listeners[e].forEach(i=>i(t))}async play(){if(!this.isPlayingValue)try{this.audioContext&&await this.ensureAudioContextRunning(),await this.mediaElement.play(),this.isPlayingValue=!0,this.isPausedValue=!1,this.isStoppedValue=!1}catch(e){if(e?.name==="AbortError")return;console.error("error trying to play media element",e),this.emit("error",e)}}pause(){this.mediaElement.pause(),this.isPlayingValue=!1,this.isPausedValue=!0}stop(){this.mediaElement.pause(),this.mediaElement.currentTime=0,this.isPlayingValue=!1,this.isPausedValue=!1,this.isStoppedValue=!0}setVolume(e){const t=Math.max(0,Math.min(1,e));this.gainNode?(this.mediaElement.volume=1,this.gainNode.gain.value=t):this.mediaElement.volume=t,this.isMutedValue=t===0}skip(e){const t=this.mediaElement.duration;if(!isFinite(t))return;const i=this.mediaElement.currentTime+e;i<0?this.mediaElement.currentTime=0:i>t?this.mediaElement.currentTime=t:this.mediaElement.currentTime=i}currentTime(){return this.mediaElement.currentTime}duration(){return this.mediaElement.duration}isPlaying(){return this.isPlayingValue}isPaused(){return this.isPausedValue}isStopped(){return this.isStoppedValue}isLoading(){return this.isLoadingValue}isLoaded(){return this.isLoadedValue}isEnded(){return this.isEndedValue}isMuted(){return this.isMutedValue}setPlaybackRate(e,t){this.mediaElement.playbackRate=e,t?"preservesPitch"in this.mediaElement?this.mediaElement.preservesPitch=!0:this.activateWebAudio().then(()=>{this.worklet?this.worklet.updatePitchFactor(1/e):r.createWorklet({ctx:this.getOrCreateAudioContext(),pitchFactor:1}).then(i=>{this.sourceNode&&this.sourceNode.disconnect(),this.worklet=i,this.sourceNode?.connect(this.worklet.workletNode),this.worklet.workletNode.connect(this.gainNode),this.worklet.updatePitchFactor(1/e)}).catch(i=>{console.warn("Failed to create preserve pitch worklet",i)})}).catch(i=>{console.warn("Web Audio unavailable, playing without pitch correction:",i)}):("preservesPitch"in this.mediaElement&&(this.mediaElement.preservesPitch=!1),this.worklet&&(this.worklet.destroy(),this.worklet=null,this.webAudioActive&&this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode.connect(this.gainNode))))}async activateWebAudio(){if(this.webAudioActive)return;if(this.usesMse){this.sourceNode=new MediaElementAudioSourceNode(this.getOrCreateAudioContext(),{mediaElement:this.mediaElement});const s=this.getOrCreateAudioContext();this.gainNode=s.createGain(),this.gainNode.gain.value=this.mediaElement.volume,this.mediaElement.volume=1,this.sourceNode.connect(this.gainNode),this.gainNode.connect(s.destination),this.webAudioActive=!0;return}const e=this.mediaElement.src;if(!e)return;const t=this.mediaElement.currentTime,i=this.isPlayingValue;i&&(this.mediaElement.pause(),this.isPlayingValue=!1),this.mediaElement.crossOrigin="anonymous",this.mediaElement.src=e,this.mediaElement.load();try{await new Promise((s,d)=>{const n=()=>{this.mediaElement.removeEventListener("canplaythrough",n),this.mediaElement.removeEventListener("error",o),s()},o=()=>{this.mediaElement.removeEventListener("canplaythrough",n),this.mediaElement.removeEventListener("error",o),d(new Error("Audio reload with CORS failed — server may not send Access-Control-Allow-Origin"))};this.mediaElement.addEventListener("canplaythrough",n),this.mediaElement.addEventListener("error",o)})}catch(s){throw this.mediaElement.removeAttribute("crossorigin"),this.mediaElement.src=e,this.mediaElement.load(),i?(await new Promise(d=>{const n=()=>{this.mediaElement.removeEventListener("canplaythrough",n),d()};this.mediaElement.addEventListener("canplaythrough",n)}),this.mediaElement.currentTime=t,await this.mediaElement.play(),this.isPlayingValue=!0,this.isPausedValue=!1):this.mediaElement.currentTime=t,s}this.mediaElement.currentTime=t,this.sourceNode=new MediaElementAudioSourceNode(this.getOrCreateAudioContext(),{mediaElement:this.mediaElement});const a=this.getOrCreateAudioContext();this.gainNode=a.createGain(),this.gainNode.gain.value=this.mediaElement.volume,this.mediaElement.volume=1,this.sourceNode.connect(this.gainNode),this.gainNode.connect(a.destination),this.webAudioActive=!0,i&&(await this.ensureAudioContextRunning(),await this.mediaElement.play(),this.isPlayingValue=!0,this.isPausedValue=!1)}get isWebAudioActive(){return this.webAudioActive}get usesMse(){return this.mseLoaderFactory!==null}tearDownWebAudio(){this.worklet&&(this.worklet.destroy(),this.worklet=null),this.sourceNode&&(this.sourceNode.disconnect(),this.sourceNode=null),this.gainNode&&(this.mediaElement.volume=this.gainNode.gain.value,this.gainNode.disconnect(),this.gainNode=null),this.webAudioActive=!1}changeSrc(e,t){if(!(this.currentHref===e||this.mediaElement.src===e)){if(this.currentHref=e,this.mediaElement.pause(),this.isPlayingValue=!1,this.isPausedValue=!1,this.isLoadedValue=!1,this.isLoadingValue=!0,this.isEndedValue=!1,this.mseLoaderFactory){this.mseLoader?.destroy(),this.mseLoader=this.mseLoaderFactory(this.mediaElement,e,t),this.mseLoader.start();return}if(this.webAudioActive){this.mediaElement.crossOrigin="anonymous",this.mediaElement.src=e,this.mediaElement.load();const i=()=>{s()},a=()=>{s(),console.warn("CORS reload failed for new track — disabling Web Audio graph:",e),this.tearDownWebAudio(),this.mediaElement.removeAttribute("crossorigin"),this.mediaElement.src=e,this.mediaElement.load()},s=()=>{this.mediaElement.removeEventListener("canplaythrough",i),this.mediaElement.removeEventListener("error",a)};this.mediaElement.addEventListener("canplaythrough",i),this.mediaElement.addEventListener("error",a)}else this.mediaElement.src=e,this.mediaElement.load()}}getMediaElement(){return this.mediaElement}destroy(){this.mseLoader?.destroy(),this.mseLoader=null}}export{u as WebAudioEngine};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Layout as l,Link as f}from"@readium/shared";import{VisualNavigator as m}from"../Navigator.js";import{getContentWidth as P}from"../helpers/dimensions.js";import{NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as d}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as y,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as p}from"../peripherals/KeyboardPeripherals.js";import{KeyboardConditionBridge as _}from"../peripherals/KeyboardConditionBridge.js";import{DivinaSpreader as b}from"./DivinaSpreader.js";import{DivinaPageManager as v}from"./DivinaPageManager.js";import{DivinaPagedPresenter as w}from"./DivinaPagedPresenter.js";import{DivinaScrolledPresenter as L}from"./DivinaScrolledPresenter.js";import{isTypedOMSupported as k}from"../epub/fxl/FXLPeripherals.js";import{DivinaNavigatorProtector as E}from"./protection/DivinaNavigatorProtector.js";import{DivinaDefaults as S}from"./preferences/DivinaDefaults.js";import{DivinaPreferences as C}from"./preferences/DivinaPreferences.js";import{DivinaSettings as g}from"./preferences/DivinaSettings.js";import{DivinaPreferencesEditor as u}from"./preferences/DivinaPreferencesEditor.js";const T=o=>({positionChanged:o.positionChanged||(()=>{}),timelineItemChanged:o.timelineItemChanged||(()=>{}),tap:o.tap||(()=>!1),click:o.click||(()=>!1),zoom:o.zoom||(()=>{}),miscPointer:o.miscPointer||(()=>{}),scroll:o.scroll||(()=>{}),customEvent:o.customEvent||(()=>{}),handleLocator:o.handleLocator||(()=>!1),contentProtection:o.contentProtection||(()=>{}),contextMenu:o.contextMenu||(()=>{}),peripheral:o.peripheral||(()=>{})});class G extends m{constructor(e,t,i,n=[],r=void 0,s={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._isNavigating=!1,this._timelineAugmented=!1,this._preferencesEditor=null,this.pool=new Map,this.pagedPresenter=null,this.scrolledPresenter=null,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._keyboardConditionBridge=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._applying=Promise.resolve(),this.pub=t,this.container=e,this.listeners=T(i),this.currentLocation=r,n.length&&(this.positions=n),this._preferences=new C(s.preferences),this._defaults=new S(s.defaults),this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this.spreader=new b(t),this._contentProtection=s.contentProtection||{},this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,s.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable||this._contentProtection.disableDragAndDrop||this._contentProtection.protectCopy)&&(this._navigatorProtector=new E(this._contentProtection),this._suspiciousActivityListener=a=>{const{type:h,...c}=a.detail;h==="context_menu"?this.listeners.contextMenu(c):this.listeners.contentProtection(h,c)},window.addEventListener(d,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardConditionBridge=new _(this._keyboardPeripherals,a=>{this._keyboardPeripheralsManager?.destroy(),this._keyboardPeripheralsManager=a.length>0?new y({keyboardPeripherals:a}):null}),this._keyboardConditionBridge.setup(),this._keyboardPeripheralListener=a=>{const h=a.detail;this.listeners.peripheral(h)},window.addEventListener(p,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(()=>this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}get manifestScrolled(){return this.pub.metadata.effectiveLayout===l.scrolled}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((n,r)=>{if(n.children?.length)return{};if(i.has(r.href))return{};const s=t.find(a=>a.href===r.href);return s?(i.add(r.href),{position:s.locations.position}):{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=e),this._wrappedTimeline}_notifyTimelineChange(e){const t=this.timeline.locate(e);t!==this._currentTimelineItem&&(this._currentTimelineItem=t,this.listeners.timelineItemChanged(t))}get layout(){return this._settings.scrolled?l.scrolled:l.fixed}get readingProgression(){return this.pub.metadata.effectiveReadingProgression}get presenter(){return this.pagedPresenter??this.scrolledPresenter}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),this._destroyed)return;this.positions?.length||(this.positions=this.synthesizePositions());const e=async(i,n)=>{const r=this.pub.get(i),s=await r.read(void 0,{signal:n});if(!s)throw new Error(`Empty resource: ${i.href}`);const a=await r.link(),h=a.type!==void 0?a.mediaType:i.mediaType;return new Blob([s],{type:h.string})},t=()=>this._settings.quality;if(this.spreader.pages.forEach(i=>{this.pool.set(i.index,new v(i,e,t))}),this.applyBackground(),this.createPresenter(),!this._destroyed)return this.resizeHandler(),this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),new Promise(i=>{if(this._destroyed)return i(!1);this.go(this.currentLocation,!1,n=>i(n))})}synthesizePositions(){const e=this.pub.readingOrder.items.length;return this.pub.readingOrder.items.map((t,i)=>t.locator.copyWithLocations({progression:0,position:i+1,totalProgression:e>0?i/e:0}))}createPresenter(){this._settings.scrolled?(this.scrolledPresenter=new L(this.container,this.spreader,this.pool,this._settings.stripWidth),this.scrolledPresenter.listener=(e,t)=>{switch(e){case"scroll":this.listeners.scroll(t);break;case"position":this.updateLocationFromScroll(t);break;case"tap":case"click":this.handlePointer(e,t);break}}):(this.pagedPresenter=new w(this.container,this.pub,this.spreader,this.pool,this._settings.spreads),this.pagedPresenter.listener=(e,t)=>{switch(e){case"no_more":this.changeSpread(1);break;case"no_less":this.changeSpread(-1);break;case"zoom":this.listeners.zoom(t);break;case"tap":case"click":this.handlePointer(e,t);break}})}async destroyPresenter(){this.pagedPresenter&&(await this.pagedPresenter.destroy(),this.pagedPresenter=null),this.scrolledPresenter&&(await this.scrolledPresenter.destroy(),this.scrolledPresenter=null)}handlePointer(e,t){const i={defaultPrevented:!1,doNotDisturb:t.doNotDisturb,interactiveElement:void 0,cssSelector:void 0,targetElement:"",targetFrameSrc:"",x:t.x,y:t.y};if((e==="click"?this.listeners.click(i):this.listeners.tap(i))||t.doNotDisturb)return;const r=window.devicePixelRatio||1;if(this._settings.scrolled){const s=this.container.clientHeight*r/4;t.y>=s&&t.y<=s*3?this.listeners.miscPointer(1):t.y<s?this.goBackward(!0,()=>{}):this.goForward(!0,()=>{})}else{const s=this.container.clientWidth*r/4;t.x>=s&&t.x<=s*3?this.listeners.miscPointer(1):t.x<s?this.goLeft(!1,()=>{}):this.goRight(!1,()=>{})}}changeSpread(e){const t=this.pagedPresenter;return!t||!(e>0?t.next():t.prev())?!1:(this.setLocationToIndex(t.currentIndex),t.update(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0)}setLocationToIndex(e){const t=this.pub.readingOrder.items[e];if(!t)return;const i=this.positions.find(n=>n.href===t.href);this.currentLocation=i??this.synthesizePositions()[e]}updateLocationFromScroll(e){const t=this.scrolledPresenter;if(!t)return;this.setLocationToIndex(e);const i=this.pub.readingOrder.items.length,n=t.currentPageProgression;this.currentLocation=this.currentLocation.copyWithLocations({progression:n,totalProgression:i>0?Math.min((e+n)/i,1):0}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation)}applyBackground(){const e=this._settings.backgroundColor;if(e){this.container.style.background=e;const t=this.isDarkColor(e);t===null?(this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")):(this.container.style.colorScheme=t?"dark":"light",this.container.style.scrollbarColor=`${t?"rgba(255, 255, 255, 0.3)":"rgba(0, 0, 0, 0.3)"} ${e}`)}else this.container.style.removeProperty("background"),this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")}isDarkColor(e){const t=this.container.ownerDocument,i=t.createElement("div");i.style.display="none",i.style.color=e,t.body.appendChild(i);const n=(t.defaultView||window).getComputedStyle(i).color;i.remove();const r=n.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);return r?(.2126*+r[1]+.7152*+r[2]+.0722*+r[3])/255<.45:null}resizeHandler(){const e=this.container.parentElement||document.documentElement,t=window.devicePixelRatio||1,i=Math.floor((P(e)-this._settings.constraint)*t)/t;k()?this.container.attributeStyleMap.set("width",CSS.px(i)):this.container.style.width=`${i}px`,this.pagedPresenter?.resizeHandler(),this.scrolledPresenter?.resizeHandler()}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(n=>n.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let n=0,r=1/0;for(let s=0;s<this.positions.length;s++){const h=this.positions[s].locations.totalProgression??s/this.positions.length,c=Math.abs(h-i);c<r&&(r=c,n=s)}e=this.positions[n].copyWithLocations(e.locations)}}return e}findReadingOrderIndex(e){const t=this.pub.readingOrder.findIndexWithHref(e);if(t>=0)return t;const i=this.pub.baseURL,n=new f({href:e}).toURL(i)??e,r=s=>(s.toURL(i)??s.href)===n;return this.pub.readingOrder.items.findIndex(s=>r(s)||!!s.alternates?.items.some(r))}go(e,t,i){e=this.completeLocator(e);const n=e.href?.split("#")[0],r=n?this.findReadingOrderIndex(n):-1;if(r<0)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0;try{if(this.scrolledPresenter){const s=e.locations?.progression||0;this.scrolledPresenter.goToItem(r,t,s),this.scrolledPresenter.update()}else this.pagedPresenter&&(this.pagedPresenter.goToItem(r,t),this.pagedPresenter.update());this.setLocationToIndex(this.pagedPresenter?this.pagedPresenter.currentIndex:r),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i(!0)}finally{this._isNavigating=!1}}goLink(e,t,i){return this.go(e.locator,t,i)}goForward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.next(e));return}t(this.changeSpread(1))}goBackward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.prev(e));return}t(this.changeSpread(-1))}scrollBy(e,t,i){if(this.scrolledPresenter){i(e>=0?this.scrolledPresenter.next(t,e):this.scrolledPresenter.prev(t,-e));return}i(this.changeSpread(e>=0?1:-1))}zoomIn(){this.pagedPresenter?.peripherals.zoomIn()}zoomOut(){this.pagedPresenter?.peripherals.zoomOut()}zoomReset(){this.pagedPresenter?.peripherals.resetZoom()}get currentLocator(){return this.currentLocation}get viewport(){return this.presenter?.viewport??{readingOrder:[],progressions:new Map,positions:null}}get isScrollStart(){const e=this.viewport.readingOrder[0];return(e?this.viewport.progressions.get(e):void 0)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return(e?this.viewport.progressions.get(e):void 0)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),this._applying=this._applying.then(()=>this.applyPreferences()),await this._applying}async applyPreferences(){const e=this._settings;if(this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this._preferencesEditor!==null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),e.backgroundColor!==this._settings.backgroundColor&&this.applyBackground(),e.constraint!==this._settings.constraint&&this.resizeHandler(),e.scrolled!==this._settings.scrolled){if(!this.presenter)return;const t=this.currentLocation;if(await this.destroyPresenter(),this._destroyed)return;this.createPresenter(),this.resizeHandler(),this.go(t,!1,()=>{});return}e.spreads!==this._settings.spreads&&this.pagedPresenter?.setSpreads(this._settings.spreads),e.stripWidth!==this._settings.stripWidth&&this.scrolledPresenter?.applyStripWidth(this._settings.stripWidth),e.quality!==this._settings.quality&&(this.pool.forEach(t=>t.unload()),this.pagedPresenter?.update(),this.scrolledPresenter?.update())}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(d,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(p,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardConditionBridge?.destroy(),this._keyboardPeripheralsManager?.destroy(),this.resizeObserver.disconnect(),await this.destroyPresenter(),this.pool.forEach(e=>e.destroy()),this.pool.clear(),Array.from(this.container.childNodes).forEach(e=>{(e.nodeType===Node.ELEMENT_NODE||e.nodeType===Node.TEXT_NODE)&&e.remove()})}}export{G as DivinaNavigator};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Page as n}from"@readium/shared";import{isTypedOMSupported as p}from"../epub/fxl/FXLPeripherals.js";import{DivinaQuality as u,selectVariant as y}from"./DivinaVariantSelector.js";const c=h=>h.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),d=new Map;function m(h,t,s,e){const r=`${h}x${t}|${s}|${e??""}`,i=d.get(r);if(i)return i;const a=Math.max(24,Math.round(Math.min(h,t)/10));s=c(s),e=e&&c(e);const o=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${h} ${t}"><rect width="100%" height="100%" fill="rgba(128,128,128,0.08)"/><text x="50%" y="50%" text-anchor="middle" dominant-baseline="central" font-family="sans-serif" font-weight="bold" font-size="${a}" fill="#999">${s}</text>`+(e?`<text x="50%" y="97%" text-anchor="middle" font-family="sans-serif" font-size="${Math.round(a/3)}" fill="#aaa">${e.length>40?"…"+e.slice(e.length-40):e}</text>`:"")+"</svg>",l=`data:image/svg+xml,${encodeURIComponent(o)}`;return d.set(r,l),l}const b=1080,f=1440;class v{constructor(t,s,e=()=>u.auto){this.objectURL=null,this.loadPromise=null,this.abortController=null,this._loaded=!1,this.destroyed=!1,this.generation=0,this.mode="paged",this.page=t,this.fetchBlob=s,this.getQuality=e,this.wrapper=document.createElement("div"),this.wrapper.style.position="relative",this.wrapper.style.overflow="hidden",this.wrapper.dataset.href=t.link.href,this.wrapper.dataset.pageNumber=`${t.number}`,this.img=document.createElement("img"),this.img.decoding="async",this.img.draggable=!1,this.img.alt=t.link.title||`Page ${t.number}`,this.img.style.display="block",this.img.style.userSelect="none",this.img.style.webkitUserSelect="none",this.img.style.webkitUserDrag="none",this.placeholder=m(this.intrinsicWidth,this.intrinsicHeight,"···",this.page.link.title?this.page.link.title:`Page ${this.page.number}`),this.img.src=this.placeholder,this.wrapper.appendChild(this.img)}get intrinsicWidth(){return this.page.link.width||(this._loaded?this.img.naturalWidth:0)||b}get intrinsicHeight(){return this.page.link.height||(this._loaded?this.img.naturalHeight:0)||f}get loaded(){return this._loaded}get element(){return this.wrapper}setMode(t){this.mode=t,p()?t==="paged"?(["margin-top","margin-right","margin-bottom","margin-left"].forEach(s=>this.wrapper.attributeStyleMap.delete(s)),this.img.attributeStyleMap.set("position","absolute"),this.img.attributeStyleMap.set("top",CSS.px(0)),this.img.attributeStyleMap.set("left",CSS.px(0)),this.img.attributeStyleMap.set("width",CSS.percent(100)),this.img.attributeStyleMap.set("height",CSS.percent(100)),this.img.attributeStyleMap.set("object-fit","contain"),this.img.attributeStyleMap.delete("aspect-ratio")):(this.wrapper.attributeStyleMap.set("float","none"),this.wrapper.attributeStyleMap.set("width",CSS.percent(100)),this.wrapper.attributeStyleMap.set("height","auto"),this.wrapper.attributeStyleMap.set("margin-top",CSS.px(0)),this.wrapper.attributeStyleMap.set("margin-bottom",CSS.px(0)),this.wrapper.attributeStyleMap.set("margin-left","auto"),this.wrapper.attributeStyleMap.set("margin-right","auto"),this.img.attributeStyleMap.set("position","static"),this.img.attributeStyleMap.delete("top"),this.img.attributeStyleMap.delete("left"),this.img.attributeStyleMap.set("width",CSS.percent(100)),this.img.attributeStyleMap.set("height","auto"),this.img.attributeStyleMap.delete("object-fit"),this.img.attributeStyleMap.set("aspect-ratio",`${this.intrinsicWidth} / ${this.intrinsicHeight}`)):t==="paged"?(this.wrapper.style.removeProperty("margin"),this.img.style.position="absolute",this.img.style.top="0",this.img.style.left="0",this.img.style.width="100%",this.img.style.height="100%",this.img.style.objectFit="contain",this.img.style.removeProperty("aspect-ratio")):(this.wrapper.style.cssFloat=this.wrapper.style.float="none",this.wrapper.style.width="100%",this.wrapper.style.height="auto",this.wrapper.style.margin="0 auto",this.img.style.position="static",this.img.style.removeProperty("top"),this.img.style.removeProperty("left"),this.img.style.width="100%",this.img.style.height="auto",this.img.style.removeProperty("object-fit"),this.img.style.aspectRatio=`${this.intrinsicWidth} / ${this.intrinsicHeight}`)}fit(t,s=!1){if(this.mode!=="paged")return;let e,r,i;s&&t!==n.center?(e=50,r=t===n.right?50:0,i="center center"):(e=100,r=0,i=t===n.left?"right center":t===n.right?"left center":"center center"),p()?(this.img.attributeStyleMap.set("width",CSS.percent(e)),this.img.attributeStyleMap.set("left",CSS.percent(r)),this.img.attributeStyleMap.set("object-position",i)):(this.img.style.width=`${e}%`,this.img.style.left=`${r}%`,this.img.style.objectPosition=i)}applyStripWidth(t){this.mode==="scrolled"&&(p()?(this.wrapper.attributeStyleMap.set("width",CSS.px(Math.round(t))),this.wrapper.attributeStyleMap.set("max-width",CSS.percent(100))):(this.wrapper.style.width=`${Math.round(t)}px`,this.wrapper.style.maxWidth="100%"))}pickVariant(){const t=window.devicePixelRatio||1,s=this.wrapper.clientWidth||0,e=this.wrapper.clientHeight||0;let r=s*t,i=e*t;if(this.mode==="paged"&&s>0&&e>0){const a=Math.min(s/this.intrinsicWidth,e/this.intrinsicHeight);r=this.intrinsicWidth*a*t,i=this.intrinsicHeight*a*t}return y(this.page.link,{targetWidth:r,targetHeight:i,axis:this.mode==="scrolled"?"width":"height",quality:this.getQuality()})}async load(){if(this._loaded||this.destroyed)return;if(this.loadPromise)return this.loadPromise;const t=this.generation;this.abortController=new AbortController;const s=this.abortController.signal;return this.loadPromise=(async()=>{try{const e=await this.fetchBlob(this.pickVariant(),s);if(this.destroyed||t!==this.generation)return;const r=URL.createObjectURL(e);try{await new Promise((i,a)=>{const o=()=>{g(),i()},l=()=>{g(),a(new Error(`Failed to decode ${this.page.link.href}`))},g=()=>{this.img.removeEventListener("load",o),this.img.removeEventListener("error",l)};this.img.addEventListener("load",o),this.img.addEventListener("error",l),this.img.src=r})}catch(i){throw URL.revokeObjectURL(r),i}if(this.destroyed||t!==this.generation){URL.revokeObjectURL(r),this.img.src===r&&(this.img.src=this.placeholder);return}if(this.objectURL=r,this._loaded=!0,this.mode==="scrolled"&&this.img.naturalWidth&&this.img.naturalHeight){const i=`${this.img.naturalWidth} / ${this.img.naturalHeight}`;p()?this.img.attributeStyleMap.set("aspect-ratio",i):this.img.style.aspectRatio=i}}catch(e){!this.destroyed&&t===this.generation&&(console.warn("Divina page load failed",this.page.link.href,e),this.img.src=m(this.intrinsicWidth,this.intrinsicHeight,"!",this.page.link.title?this.page.link.title:`Page ${this.page.number}`))}finally{t===this.generation&&(this.loadPromise=null)}})(),this.loadPromise}unload(){!this._loaded&&!this.loadPromise||(this.generation++,this._loaded=!1,this.loadPromise=null,this.abortController?.abort(),this.abortController=null,this.img.src=this.placeholder,this.objectURL&&(URL.revokeObjectURL(this.objectURL),this.objectURL=null))}destroy(){this.destroyed=!0,this.unload(),this.wrapper.remove()}}export{v as DivinaPageManager,m as placeholderSVG};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ReadingProgression as p,Page as u}from"@readium/shared";import{isTypedOMSupported as o}from"../epub/fxl/FXLPeripherals.js";import{DivinaPeripherals as c}from"./DivinaPeripherals.js";const m=8,S=4,g=300,l=150,d=500;class E{constructor(t,e,s,i,r){this.width=0,this.height=0,this.currentSlide=0,this.orientationInternal=-1,this.destroyed=!1,this.loadTimers=new Map,this.listener=()=>{},this.bookScale=null,this.bookTranslate=null,this.bookTransform=null,this.container=t,this.pub=e,this.spreader=s,this.pool=i,this.spread=r,this.containerHeightCached=t.clientHeight,this.bookElement=document.createElement("div"),this.bookElement.ariaLabel="Book",this.bookElement.tabIndex=-1,this.updateBookStyle(!0),this.spineElement=document.createElement("div"),this.spineElement.ariaLabel="Spine",this.bookElement.appendChild(this.spineElement),this.container.appendChild(this.bookElement);const n=document.createDocumentFragment();this.spreader.pages.forEach(h=>{const a=this.pool.get(h.index);a.setMode("paged"),a.wrapper.style.cssFloat=a.wrapper.style.float=this.rtl?"right":"left",a.wrapper.style.contain="strict",n.appendChild(a.wrapper)}),this.spineElement.appendChild(n),this.updateSpineStyle(!1),this.updateSlotSizes(),this.peripherals=new c(this)}get rtl(){return this.pub.metadata.effectiveReadingProgression===p.rtl}get single(){return!this.spread||this.portrait}get perPage(){return this.spread&&!this.portrait?2:1}get threshold(){return 50}get portrait(){return this.orientationInternal===-1&&(this.orientationInternal=this.containerHeightCached>this.container.clientWidth?1:0),this.orientationInternal===1}get slength(){return this.spreader.pages.length}get length(){return this.single?this.slength:this.spreader.slotCount}slotEdge(t){const e=window.devicePixelRatio||1;return Math.round(t*(this.width/this.perPage)*e)/e}get offset(){return(this.rtl?1:-1)*this.slotEdge(this.currentSlide)}get doNotDisturb(){return this.peripherals.pan.touchID>0}get currentIndex(){return this.single?Math.max(0,Math.min(this.currentSlide,this.slength-1)):this.spreader.itemOfSlot(this.currentSlide)}get currentSpread(){return this.perPage<2?[this.spreader.pages[this.currentIndex]]:this.spreader.spreadOfItem(this.currentIndex)}updateDimensions(){this.width=this.bookElement.clientWidth,this.height=this.bookElement.clientHeight}updateBookStyle(t=!1){if(t){const r={overflow:"hidden",direction:this.pub.metadata.effectiveReadingProgression,cursor:"",height:"100%",width:"100%",position:"relative",outline:"none",transition:this.peripherals?.dragState?"none":"transform .15s ease-in-out",touchAction:"none"};Object.assign(this.bookElement.style,r)}const e=this.peripherals?.scale||1,s=this.peripherals?.pan.translateX||0,i=this.peripherals?.pan.translateY||0;o()?(this.bookTransform||(this.bookScale=new CSSScale(1,1),this.bookTranslate=new CSSTranslate(CSS.px(0),CSS.px(0),CSS.px(0)),this.bookTransform=new CSSTransformValue([this.bookScale,this.bookTranslate])),this.bookScale.x.value=e,this.bookScale.y.value=e,this.bookTranslate.x.value=s,this.bookTranslate.y.value=i,this.bookElement.attributeStyleMap.set("transform",this.bookTransform)):this.bookElement.style.transform=`scale(${e}) translate3d(${s}px, ${i}px, 0px)`}updateSpineStyle(t,e=!0){if(this.updateDimensions(),o())this.spineElement.attributeStyleMap.set("transition",new CSSUnparsedValue([t?`all ${e?l:d}ms ease-out`:"all 0ms ease-out"])),this.spineElement.attributeStyleMap.set("width",CSS.px(this.slotEdge(this.length))),this.spineElement.attributeStyleMap.set("height",CSS.percent(100)),this.transform!==void 0?this.spineElement.attributeStyleMap.set("transform",new CSSTransformValue([new CSSTranslate(CSS.px(this.transform||0),CSS.px(0),CSS.px(0))])):this.spineElement.attributeStyleMap.delete("transform"),this.spineElement.attributeStyleMap.set("contain",new CSSUnparsedValue(["content"]));else{const s={transition:t?`all ${e?l:d}ms ease-out`:"all 0ms ease-out",width:`${this.slotEdge(this.length)}px`,height:"100%",transform:this.transform!==void 0?`translate3d(${this.transform}px, 0px, 0px)`:"",contain:"content"};Object.assign(this.spineElement.style,s)}}updateSlotSizes(){this.updateDimensions();const t=o();this.spreader.pages.forEach(e=>{const s=this.pool.get(e.index),i=!this.single&&this.spreader.isDouble(e.index)?2:1,r=this.single?e.index:this.spreader.slotOfItem(e.index),n=this.slotEdge(r+i)-this.slotEdge(r);t?(s.wrapper.attributeStyleMap.set("width",CSS.px(n)),s.wrapper.attributeStyleMap.set("height",CSS.px(this.height))):(s.wrapper.style.width=`${n}px`,s.wrapper.style.height=`${this.height}px`)})}reAlign(t=this.currentSlide){return t%2&&!this.single&&t++,t}slideToCurrent(t,e=!0){this.updateDimensions();const s=i=>{this.transform=this.offset,this.updateSpineStyle(i,e),this.deselect()};t?requestAnimationFrame(()=>{requestAnimationFrame(()=>s(!0))}):s(!1)}bounce(t=!1){requestAnimationFrame(()=>{this.transform=this.offset+50*(t?1:-1),this.updateSpineStyle(!0,!0),setTimeout(()=>{this.destroyed||(this.transform=this.offset,this.updateSpineStyle(!0,!0))},100)})}onChange(){this.peripherals.scale=1,this.peripherals.pan.translateX=0,this.peripherals.pan.translateY=0,this.updateBookStyle()}next(){if(this.length<=this.perPage)return!1;const t=this.currentSlide;return this.currentSlide=Math.min(this.currentSlide+this.perPage,this.length-this.perPage),this.currentSlide=this.reAlign(),t!==this.currentSlide?(this.slideToCurrent(!0),this.onChange(),!0):(this.bounce(this.rtl),!1)}prev(){if(this.length<=this.perPage)return!1;const t=this.currentSlide;return this.currentSlide=this.reAlign(Math.max(this.currentSlide-this.perPage,0)),t!==this.currentSlide?(this.slideToCurrent(!0),this.onChange(),!0):(this.bounce(!this.rtl),!1)}slideForItem(t){const e=Math.max(0,Math.min(t,this.slength-1));return this.single?e:this.spreader.slotOfItem(this.spreader.spreadOfItem(e)[0].index)}goToItem(t,e=!0){const s=this.slideForItem(t);return s===this.currentSlide?!1:(this.currentSlide=s,this.slideToCurrent(e),this.onChange(),!0)}async update(){if(this.destroyed)return;const t=this.currentIndex,e=this.currentSpread,s=new Set(e.map(i=>i.index));this.spreader.pages.forEach(i=>{const r=this.pool.get(i.index),n=Math.abs(i.index-t);if(n>m){const h=this.loadTimers.get(i.index);h&&(clearTimeout(h),this.loadTimers.delete(i.index)),r.unload()}else if(n<=S&&!s.has(i.index)&&!r.loaded&&!this.loadTimers.has(i.index)){const h=window.setTimeout(()=>{this.loadTimers.delete(i.index),this.destroyed||r.load()},g);this.loadTimers.set(i.index,h)}}),await Promise.all(e.map(i=>{const r=this.pool.get(i.index),n=this.loadTimers.get(i.index);return n&&(clearTimeout(n),this.loadTimers.delete(i.index)),this.placePage(e,i),r.load()}))}placePage(t,e){const s=this.pool.get(e.index);s&&(this.perPage>1&&t.length===1&&!e.isLandscape&&e.page!==u.center?s.fit(e.page,!0):s.fit(this.spreader.spreadPosition(t,e,this.perPage)))}get currentBounds(){const t={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentSpread.forEach(e=>{const s=this.pool.get(e.index);if(!s)return;const i=s.img.getBoundingClientRect();t.x=Math.min(t.x,i.x),t.y=Math.min(t.y,i.y),t.width+=i.width,t.height=Math.max(t.height,i.height),t.top=Math.min(t.top,i.top),t.right=Math.min(t.right,i.right),t.bottom=Math.min(t.bottom,i.bottom),t.left=Math.min(t.left,i.left)}),t}get viewport(){const t={readingOrder:[],progressions:new Map,positions:null},e=[];return this.currentSpread.forEach(s=>{t.readingOrder.push(s.link.href),t.progressions.set(s.link.href,{start:0,end:1}),e.push(s.number)}),t.positions=e,t}resizeHandler(t=!0,e=!0){const s=this.currentIndex;this.containerHeightCached=this.container.clientHeight,this.orientationInternal=-1,this.currentSlide=this.slideForItem(s),this.updateSpineStyle(!1),this.updateSlotSizes(),t&&this.slideToCurrent(!e,e);const i=this.currentSpread;i.forEach(r=>this.placePage(i,r))}setSpreads(t){if(this.spread===t)return;const e=this.currentIndex;this.spread=t,this.currentSlide=this.slideForItem(e),requestAnimationFrame(()=>{this.destroyed||(this.resizeHandler(!0),this.update())})}deselect(){this.container.ownerDocument.defaultView?.getSelection()?.removeAllRanges()}async destroy(){this.destroyed=!0,this.loadTimers.forEach(t=>clearTimeout(t)),this.loadTimers.clear(),this.peripherals.destroy(),this.spineElement.replaceChildren(),this.bookElement.remove()}}export{E as DivinaPagedPresenter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{FXLCoordinator as X}from"../epub/fxl/FXLCoordinator.js";import{isTypedOMSupported as v}from"../epub/fxl/FXLPeripherals.js";const l=6,d=1.02,u=.5,p=50,g=5,f=200,w=300,T=60;class H{constructor(t){this.dragState=0,this.minimumMoved=!1,this.pan={startX:0,endX:0,startY:0,overscrollX:0,overscrollY:0,letItGo:!1,preventClick:!1,translateX:0,translateY:0,touchID:0},this.pinch={startDistance:0,startScale:0,target:{X:0,Y:0},touchN:0,startTranslate:{X:0,Y:0}},this._scale=1,this.scaleDebouncer=0,this.frameBounds=null,this.destroyed=!1,this.mouseDown=null,this.clickTimer=0,this.lastTouchEnd=0,this.tapTimer=0,this.lastTapTime=0,this.lastTapX=0,this.lastTapY=0,this.wheelHot=!1,this.wheelLastDir=0,this.wheelLastMag=0,this.wheelDecelCount=0,this.wheelLastEvent=0,this.wheelCooldownTimer=0,this.btouchstartHandler=this.touchstartHandler.bind(this),this.btouchendHandler=this.touchendHandler.bind(this),this.btouchmoveHandler=this.touchmoveHandler.bind(this),this.bdblclickHandler=this.dblclickHandler.bind(this),this.bmousedownHandler=this.mousedownHandler.bind(this),this.bmouseupHandler=this.mouseupHandler.bind(this),this.bmousemoveHandler=this.mousemoveHandler.bind(this),this.bwheelHandler=this.wheelHandler.bind(this),this.moveFrame=0,this.dragTranslate=null,this.dragTransform=null,this.manager=t,this.coordinator=new X,this.observe(this.manager.spineElement),this.manager.bookElement.addEventListener("wheel",this.bwheelHandler,{passive:!1})}get scale(){return this._scale}set scale(t){isNaN(t)&&(t=1),window.clearTimeout(this.scaleDebouncer),this.scaleDebouncer=window.setTimeout(()=>{this.dragState===0&&this.scale<d&&(this.pan.translateX=0,this.pan.translateY=0,this.clearPan(),this.manager.updateBookStyle()),this.manager.listener("zoom",t)},100),this._scale=t}observe(t){t.addEventListener("touchstart",this.btouchstartHandler),t.addEventListener("touchend",this.btouchendHandler),t.addEventListener("touchmove",this.btouchmoveHandler,{passive:!0}),t.addEventListener("dblclick",this.bdblclickHandler,{passive:!0}),t.addEventListener("mousedown",this.bmousedownHandler),t.addEventListener("mouseup",this.bmouseupHandler),t.addEventListener("mousemove",this.bmousemoveHandler)}unobserve(t){t.removeEventListener("touchstart",this.btouchstartHandler),t.removeEventListener("touchend",this.btouchendHandler),t.removeEventListener("touchmove",this.btouchmoveHandler),t.removeEventListener("dblclick",this.bdblclickHandler),t.removeEventListener("mousedown",this.bmousedownHandler),t.removeEventListener("mouseup",this.bmouseupHandler),t.removeEventListener("mousemove",this.bmousemoveHandler)}destroy(){this.destroyed=!0,this.unobserve(this.manager.spineElement),this.manager.bookElement.removeEventListener("wheel",this.bwheelHandler),window.clearTimeout(this.scaleDebouncer),window.clearTimeout(this.wheelCooldownTimer),window.clearTimeout(this.clickTimer),window.clearTimeout(this.tapTimer),cancelAnimationFrame(this.moveFrame)}clearPan(){this.pan.letItGo=!1,this.pan.touchID=0,this.pan.endX=0,this.pan.overscrollX=0,this.pan.overscrollY=0}clearPinch(){this.pinch={startDistance:0,startScale:this.pinch.startScale,target:{X:0,Y:0},touchN:0,startTranslate:{X:0,Y:0}}}get isScaled(){return this.scale>1}resetZoom(){this.scale=1,this.pan.translateX=0,this.pan.translateY=0,this.manager.updateBookStyle()}emitPointer(t,e,i){const a=this.manager.bookElement.getBoundingClientRect(),h=window.devicePixelRatio||1,n={x:(e-a.left)*h,y:(i-a.top)*h,clientX:e,clientY:i,doNotDisturb:this.pan.touchID>0||this.dragState>0};this.manager.listener(t,n)}touchstartHandler(t){if(["TEXTAREA","OPTION","INPUT","SELECT"].indexOf(t.target.nodeName)!==-1)return;switch(t.stopPropagation(),this.frameBounds=this.manager.currentBounds,this.coordinator.refreshOuterPixels(this.frameBounds),t.touches.length){case 3:return;case 2:{t.preventDefault(),this.pinch.startDistance=this.coordinator.getTouchDistance(t);const a=this.startTouch(t);this.pan.startX=a.X,this.pan.startY=a.Y,this.dragState=2,this.manager.updateBookStyle(!0),this.isScaled?(this.pinch.target.X-=this.pan.translateX*(this.pinch.startScale/this.scale),this.pinch.target.Y-=this.pan.translateY*(this.pinch.startScale/this.scale),this.pinch.target={X:0,Y:0},this.pinch.startScale=1/this.scale):(this.pinch.target={X:0,Y:0},this.pinch.startScale=this.scale),this.pinch.startTranslate={X:this.pan.translateX,Y:this.pan.translateY};return}case 1:this.pan.touchID=t.touches[0].identifier;default:this.dragState<1&&(this.dragState=1),this.manager.updateBookStyle(!0)}this.manager.updateSpineStyle(!1);const i=this.startTouch(t);this.pan.startX=i.X,this.pan.startY=i.Y}startTouch(t){const e=this.coordinator.getTouchCenter(t)||this.coordinator.getBibiEventCoord(t);return{X:e.X-this.manager.width/2-this.pan.translateX*this.scale+this.manager.width/2,Y:e.Y-this.manager.height/2-this.pan.translateY*this.scale+this.manager.height/2}}touchendHandler(t){if(t.stopPropagation(),!t.touches||t.touches.length===0){const e=this.pinch.touchN>0;if(this.pan.endX&&!this.isScaled)this.pinch.touchN&&(this.pan.endX=this.pan.startX),this.updateAfterDrag();else if(!this.pinch.touchN&&Math.abs(this.pan.overscrollX)>p&&Math.abs(this.pan.overscrollY)<p/2)this.pan.startX=0,this.pan.endX=-this.pan.overscrollX,this.updateAfterDrag();else if(!this.minimumMoved&&!e&&t.changedTouches?.length===1){t.cancelable&&t.preventDefault(),this.lastTouchEnd=performance.now(),this.dragState=0,this.clearPan();const{clientX:i,clientY:a}=t.changedTouches[0],h=performance.now();h-this.lastTapTime<w&&Math.abs(i-this.lastTapX)+Math.abs(a-this.lastTapY)<T?(window.clearTimeout(this.tapTimer),this.lastTapTime=0,this.toggleZoom(i,a)):(this.lastTapTime=h,this.lastTapX=i,this.lastTapY=a,window.clearTimeout(this.tapTimer),this.tapTimer=window.setTimeout(()=>this.emitPointer("tap",i,a),w))}this.dragState=0,this.minimumMoved=!1,this.clearPinch()}else if(t.touches.length===1){this.dragState=1,t.touches[0].identifier!==this.pan.touchID&&(this.pan.touchID=t.touches[0].identifier);const e=this.startTouch(t);this.pan.startX=e.X,this.pan.startY=e.Y}window.setTimeout(()=>{this.destroyed||(this.manager.updateBookStyle(!0),this.dragState===0&&(this.scale<d&&(this.pan.translateX=0,this.pan.translateY=0),this.clearPan()),this.manager.updateBookStyle(!0))},50)}touchmoveHandler(t){t.stopPropagation();const e=this.coordinator.getBibiEventCoord(t);Math.abs(this.pan.startY-e.Y)+Math.abs(this.pan.startX-e.X)>g&&(this.minimumMoved||(this.manager.deselect(),this.minimumMoved=!0),this.dragState<1&&(this.dragState=1));const i=this.coordinator?.getTouchDistance(t);let a=!1;const h=this.scale;if(this.dragState===2&&i){if(this.pinch.touchN++,this.pinch.touchN<4)return;let n=i/this.pinch.startDistance*this.scale;n>=l&&(n=l),n<=d&&(n=1),this.scale=n,this.pinch.startDistance=i,a=!0}if(this.pan.letItGo===!1&&(this.pan.letItGo=Math.abs(this.pan.startY-e.Y)<Math.abs(this.pan.startX-e.X)),this.dragState>0&&this.isScaled||this.dragState>1){if(this.dragState===1){const s={X:e.X-this.manager.width/2,Y:e.Y-this.manager.height/2};this.pan.translateX=(s.X-(this.pan.startX-this.manager.width/2))*1/this.scale,this.pan.translateY=(s.Y-(this.pan.startY-this.manager.height/2))*1/this.scale}else if(this.dragState===2){const s=this.coordinator.getTouchCenter(t);s.X-=this.manager.width/2,s.Y-=this.manager.height/2;let o=-s.X/h;o+=s.X/this.scale,this.pinch.target.X+=o,s.X+=this.pinch.target.X*this.scale/this.pinch.startScale;let c=-s.Y/h;c+=s.Y/this.scale,this.pinch.target.Y+=c,s.Y+=this.pinch.target.Y*this.scale/this.pinch.startScale,this.pan.translateX=(s.X-(this.pan.startX-this.manager.width/2))*1/this.scale,this.pan.translateY=(s.Y-(this.pan.startY-this.manager.height/2))*1/this.scale}const n=this.frameBounds.width/6,r=this.frameBounds.height/6;this.pan.translateX<-n&&(this.pan.overscrollX=-(n+this.pan.translateX),this.pan.translateX=-n),this.pan.translateY<-r&&(this.pan.overscrollY=-(r+this.pan.translateY),this.pan.translateY=-r),this.pan.translateX>n&&(this.pan.overscrollX=n-this.pan.translateX,this.pan.translateX=n),this.pan.translateY>r&&(this.pan.overscrollY=r-this.pan.translateY,this.pan.translateY=r),a=!0}if(a){this.manager.updateBookStyle();return}if(this.dragState>0&&this.pan.letItGo){this.pan.endX=e.X;const r=this.manager.currentSlide*(this.manager.width/this.manager.perPage),s=this.pan.endX-this.pan.startX,o=this.manager.rtl?r+s:r-s,c=window.devicePixelRatio||1,m=Math.round((this.manager.rtl?1:-1)*o*c)/c;cancelAnimationFrame(this.moveFrame),this.moveFrame=requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.destroyed||(v()?(this.dragTransform||(this.dragTranslate=new CSSTranslate(CSS.px(0),CSS.px(0),CSS.px(0)),this.dragTransform=new CSSTransformValue([this.dragTranslate])),this.dragTranslate.x.value=m,this.manager.spineElement.attributeStyleMap.set("transform",this.dragTransform)):this.manager.spineElement.style.transform=`translate3d(${m}px, 0, 0)`)})})}}toggleZoom(t,e){if(this.isScaled){this.resetZoom();return}const i=this.manager.bookElement.getBoundingClientRect(),a=t-i.left,h=e-i.top;this.frameBounds=this.manager.currentBounds;const n=this.frameBounds.width/6,r=this.frameBounds.height/6;this.scale=2,this.pan.translateX=Math.max(-n,Math.min(n,this.manager.width/2-a)),this.pan.translateY=Math.max(-r,Math.min(r,this.manager.height/2-h)),this.manager.updateBookStyle()}zoomBy(t){let e=this.scale+t;e>=l&&(e=l),e<=d&&(e=1),this.scale=e,e===1&&(this.pan.translateX=0,this.pan.translateY=0),this.manager.updateBookStyle()}zoomIn(){this.zoomBy(u)}zoomOut(){this.zoomBy(-u)}dblclickHandler(t){window.clearTimeout(this.clickTimer),this.toggleZoom(t.clientX,t.clientY)}addTouch(t){t.touches=[{pageX:t.pageX,pageY:t.pageY}]}mousedownHandler(t){this.mouseDown={X:t.clientX,Y:t.clientY},this.isScaled&&(this.addTouch(t),this.touchstartHandler(t))}mouseupHandler(t){const e=this.mouseDown;if(this.mouseDown=null,this.isScaled&&this.touchendHandler(t),!(performance.now()-this.lastTouchEnd<700||t.detail>1)&&e&&t.button===0&&Math.abs(t.clientX-e.X)+Math.abs(t.clientY-e.Y)<=g){const{clientX:i,clientY:a}=t;window.clearTimeout(this.clickTimer),this.clickTimer=window.setTimeout(()=>this.emitPointer("click",i,a),250)}}mousemoveHandler(t){this.isScaled&&t.buttons>0&&(t.preventDefault(),this.addTouch(t),this.touchmoveHandler(t))}wheelHandler(t){if(t.preventDefault(),t.ctrlKey){let o=this.scale*(1-t.deltaY*.01);o>=l&&(o=l),o<=d&&(o=1),this.scale=o,this.manager.updateBookStyle();return}const e=Math.abs(t.deltaX)>Math.abs(t.deltaY),i=e?t.deltaX:t.deltaY,a=Math.abs(i);if(a<1)return;let h=Math.sign(i);e&&this.manager.rtl&&(h=-h);const n=performance.now(),r=n-this.wheelLastEvent;this.wheelLastEvent=n;let s=null;r>f?s="start":this.wheelLastDir!==0&&h!==this.wheelLastDir?s="reverse":this.wheelDecelCount>=3&&a>this.wheelLastMag*1.5&&(s="serial"),this.wheelDecelCount=a<=this.wheelLastMag?this.wheelDecelCount+1:0,this.wheelLastMag=a,this.wheelLastDir=h,s!==null&&(!this.wheelHot||s==="reverse"||s==="serial")&&(this.wheelHot=!0,(s==="serial"||s==="reverse")&&(this.wheelDecelCount=0),this.manager.listener(h>0?"no_more":"no_less",void 0)),window.clearTimeout(this.wheelCooldownTimer),this.wheelCooldownTimer=window.setTimeout(()=>{this.wheelHot=!1,this.wheelLastDir=0,this.wheelLastMag=0,this.wheelDecelCount=0},f)}updateAfterDrag(){const t=(this.manager.rtl?-1:1)*(this.pan.endX-this.pan.startX),e=Math.abs(t);t>0&&e>this.manager.threshold&&this.manager.length>this.manager.perPage?this.manager.listener("no_less",void 0):t<0&&e>this.manager.threshold&&this.manager.length>this.manager.perPage&&this.manager.listener("no_more",void 0),this.manager.slideToCurrent(!0,!0)}}export{H as DivinaPeripherals};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class c{constructor(t,e,s,i){this.destroyed=!1,this.scrollRAF=0,this.restoreRAF=0,this.positionTimer=0,this.lastScrollTop=0,this.fraction=0,this.pageTops=[],this.pageHeights=[],this.stripHeightCached=0,this.viewportHeightCached=0,this.loadedIndices=new Set,this.lastWindowIndex=-1,this.programmaticScroll=!1,this.programmaticTimer=0,this.scrollTarget=null,this.animating=!1,this.animRAF=0,this.animLastTime=0,this.listener=()=>{},this.bscrollHandler=this.scrollHandler.bind(this),this.bscrollendHandler=this.scrollendHandler.bind(this),this.banimStep=this.animStep.bind(this),this.buserTakeoverHandler=this.userTakeoverHandler.bind(this),this.bmousedownHandler=this.mousedownHandler.bind(this),this.bclickHandler=this.clickHandler.bind(this),this.btouchendHandler=this.touchendHandler.bind(this),this.btouchstartHandler=this.touchstartHandler.bind(this),this.touchStartY=null,this.lastTouchEnd=0,this.mouseDownPos=null,this.container=t,this.spreader=e,this.pool=s,this.stripWidth=i,this.scrollerElement=document.createElement("div"),this.scrollerElement.ariaLabel="Book",this.scrollerElement.tabIndex=-1,Object.assign(this.scrollerElement.style,{overflowY:"auto",overflowX:"hidden",height:"100%",width:"100%",position:"relative",outline:"none",overscrollBehavior:"contain"});const r=document.createDocumentFragment();this.spreader.pages.forEach(o=>{const n=this.pool.get(o.index);n.setMode("scrolled"),n.wrapper.style.removeProperty("contain"),r.appendChild(n.wrapper)}),this.scrollerElement.appendChild(r),this.container.appendChild(this.scrollerElement),this.applyStripWidth(i),this.scrollerElement.addEventListener("scroll",this.bscrollHandler,{passive:!0}),this.scrollerElement.addEventListener("scrollend",this.bscrollendHandler),this.scrollerElement.addEventListener("wheel",this.buserTakeoverHandler,{passive:!0}),this.scrollerElement.addEventListener("mousedown",this.bmousedownHandler),this.scrollerElement.addEventListener("mouseup",this.bclickHandler),this.scrollerElement.addEventListener("touchend",this.btouchendHandler),this.scrollerElement.addEventListener("touchstart",this.btouchstartHandler,{passive:!0})}get displayWidth(){return Math.max(1,Math.min(this.stripWidth,this.scrollerElement.clientWidth||this.container.clientWidth))}refreshLayoutCache(){this.viewportHeightCached=this.scrollerElement.clientHeight,this.stripHeightCached=this.scrollerElement.scrollHeight;const t=this.spreader.pages.length;this.pageTops=new Array(t),this.pageHeights=new Array(t);for(const e of this.spreader.pages){const s=this.pool.get(e.index).wrapper;this.pageTops[e.index]=s.offsetTop,this.pageHeights[e.index]=Math.max(1,s.offsetHeight)}}indexAtOffset(t){const e=this.pageTops;let s=0,i=e.length-1,r=0;for(;s<=i;){const o=s+i>>1;e[o]<=t?(r=o,s=o+1):i=o-1}return r}applyStripWidth(t){this.stripWidth=t;const e=this.fraction,s=this.displayWidth;this.spreader.pages.forEach(i=>{this.pool.get(i.index)?.applyStripWidth(s)}),this.refreshLayoutCache(),this.restoreFraction(e)}restoreFraction(t){cancelAnimationFrame(this.restoreRAF),this.restoreRAF=requestAnimationFrame(()=>{if(this.destroyed)return;const e=t*this.stripHeightCached;Math.abs(this.scrollerElement.scrollTop-e)>=1&&(this.beginProgrammaticScroll(),this.scrollTarget=e,this.scrollerElement.scrollTop=e),this.updateFraction()})}updateFraction(){const t=this.stripHeightCached;this.fraction=t>0?this.scrollerElement.scrollTop/t:0}pageTop(t){return this.pageTops[t]??0}pageHeight(t){return this.pageHeights[t]??1}get currentIndex(){return this.pageTops.length?this.indexAtOffset(this.scrollerElement.scrollTop+this.viewportHeightCached*.5):0}get currentPageProgression(){const t=this.currentIndex;return Math.max(0,Math.min(1,(this.scrollerElement.scrollTop-this.pageTop(t))/this.pageHeight(t)))}beginProgrammaticScroll(){this.programmaticScroll=!0,window.clearTimeout(this.programmaticTimer),this.programmaticTimer=window.setTimeout(()=>{this.programmaticScroll=!1,this.scrollTarget=null,this.settleWindow()},1200)}scrollendHandler(){this.animating||(window.clearTimeout(this.programmaticTimer),this.programmaticScroll=!1,this.scrollTarget=null,this.settleWindow())}settleWindow(){if(this.destroyed||!this.pageTops.length)return;const t=this.currentIndex;this.lastWindowIndex=t,this.updateWindow(t)}userTakeoverHandler(){window.clearTimeout(this.programmaticTimer),this.programmaticScroll=!1,this.scrollTarget=null,this.stopAnimation()}scrollHandler(){this.destroyed||(cancelAnimationFrame(this.scrollRAF),this.scrollRAF=requestAnimationFrame(()=>{if(this.destroyed)return;const t=this.scrollerElement.scrollTop,e=t-this.lastScrollTop;this.lastScrollTop=t,Math.abs(this.scrollerElement.scrollHeight-this.stripHeightCached)>1&&this.refreshLayoutCache(),this.updateFraction(),!this.programmaticScroll&&e!==0&&this.listener("scroll",e);const s=this.currentIndex;s!==this.lastWindowIndex&&!this.programmaticScroll&&(this.lastWindowIndex=s,this.updateWindow(s)),window.clearTimeout(this.positionTimer),this.positionTimer=window.setTimeout(()=>{this.destroyed||this.listener("position",this.currentIndex)},150)}))}updateWindow(t){const e=this.spreader.pages.length;for(let s=Math.max(0,t-5);s<=Math.min(e-1,t+5);s++)this.pool.get(s)?.load(),this.loadedIndices.add(s);for(const s of this.loadedIndices)Math.abs(s-t)>10&&(this.pool.get(s)?.unload(),this.loadedIndices.delete(s))}touchstartHandler(t){this.userTakeoverHandler(),this.touchStartY=t.touches.length===1?t.touches[0].clientY:null}touchendHandler(t){if(this.touchStartY===null||t.changedTouches.length!==1)return;const e=Math.abs(t.changedTouches[0].clientY-this.touchStartY);this.touchStartY=null,e<=5&&(t.cancelable&&t.preventDefault(),this.lastTouchEnd=performance.now(),this.emitPointer("tap",t.changedTouches[0].clientX,t.changedTouches[0].clientY))}mousedownHandler(t){this.mouseDownPos=t.button===0?{x:t.clientX,y:t.clientY}:null}clickHandler(t){if(t.button!==0||this.mouseDownPos===null)return;const e=Math.abs(t.clientX-this.mouseDownPos.x)+Math.abs(t.clientY-this.mouseDownPos.y);this.mouseDownPos=null,!(performance.now()-this.lastTouchEnd<700)&&e<=5&&this.emitPointer("click",t.clientX,t.clientY)}emitPointer(t,e,s){const i=this.scrollerElement.getBoundingClientRect(),r=window.devicePixelRatio||1;this.listener(t,{x:(e-i.left)*r,y:(s-i.top)*r,clientX:e,clientY:s,doNotDisturb:!1})}next(t=!0,e){const s=this.scrollerElement.scrollHeight-this.scrollerElement.clientHeight,i=this.scrollTarget??this.scrollerElement.scrollTop;if(i>=s-1)return!1;let r=Math.min(i+(e??this.viewportHeightCached*.8),s);return t&&(r=Math.min(r,this.scrollerElement.scrollTop+this.viewportHeightCached*1.5)),this.scrollToTarget(r,t),!0}prev(t=!0,e){const s=this.scrollTarget??this.scrollerElement.scrollTop;if(s<=1)return!1;let i=Math.max(s-(e??this.viewportHeightCached*.8),0);return t&&(i=Math.max(i,this.scrollerElement.scrollTop-this.viewportHeightCached*1.5)),this.scrollToTarget(i,t),!0}scrollToTarget(t,e){if(this.beginProgrammaticScroll(),this.scrollTarget=t,!e){this.stopAnimation(),this.scrollerElement.scrollTo({top:t,behavior:"auto"});return}this.animating||(this.animating=!0,this.animLastTime=performance.now(),this.animRAF=requestAnimationFrame(this.banimStep))}animStep(t){if(this.destroyed)return;const e=this.scrollTarget;if(e===null){this.stopAnimation();return}const s=Math.min(Math.max(t-this.animLastTime,0)/1e3,.1);this.animLastTime=t;const i=this.scrollerElement,r=e-i.scrollTop;if(Math.abs(r)<=1){i.scrollTop=e,this.stopAnimation();return}const o=this.viewportHeightCached*8*s;let n=r*Math.min(1,20*s);Math.abs(n)>o&&(n=Math.sign(r)*o),i.scrollTop+=n,this.animRAF=requestAnimationFrame(this.banimStep)}stopAnimation(){this.animating=!1,cancelAnimationFrame(this.animRAF)}goToItem(t,e=!1,s=0){cancelAnimationFrame(this.restoreRAF);const i=Math.max(0,Math.min(t,this.spreader.pages.length-1)),r=this.pageTop(i)+s*this.pageHeight(i);return Math.abs(this.scrollerElement.scrollTop-r)<1?!1:(this.scrollToTarget(r,e),e||this.updateFraction(),!0)}async update(){if(this.destroyed)return;const t=this.currentIndex;this.lastWindowIndex=t,this.updateWindow(t);const e=this.pool.get(t);e&&await e.load()}get atStart(){return this.scrollerElement.scrollTop<=1}get atEnd(){return this.scrollerElement.scrollTop>=this.stripHeightCached-this.viewportHeightCached-1}get viewport(){const t={readingOrder:[],progressions:new Map,positions:null};if(!this.pageTops.length)return t;const e=this.scrollerElement.scrollTop,s=e+this.viewportHeightCached,i=[];for(let r=this.indexAtOffset(e);r<this.spreader.pages.length;r++){const o=this.pageTop(r);if(o>=s)break;const n=this.pageHeight(r);if(o+n<=e)continue;const l=this.spreader.pages[r],h={start:Math.max(0,(e-o)/n),end:Math.min(1,(s-o)/n)};t.readingOrder.push(l.link.href),t.progressions.set(l.link.href,h),i.push(l.number)}return t.positions=i.length?i:null,t}resizeHandler(){const t=this.fraction,e=this.displayWidth;this.spreader.pages.forEach(s=>{this.pool.get(s.index)?.applyStripWidth(e)}),this.refreshLayoutCache(),this.restoreFraction(t)}async destroy(){this.destroyed=!0,cancelAnimationFrame(this.scrollRAF),cancelAnimationFrame(this.restoreRAF),cancelAnimationFrame(this.animRAF),window.clearTimeout(this.positionTimer),window.clearTimeout(this.programmaticTimer),this.scrollerElement.removeEventListener("scroll",this.bscrollHandler),this.scrollerElement.removeEventListener("scrollend",this.bscrollendHandler),this.scrollerElement.removeEventListener("wheel",this.buserTakeoverHandler),this.scrollerElement.removeEventListener("mousedown",this.bmousedownHandler),this.scrollerElement.removeEventListener("mouseup",this.bclickHandler),this.scrollerElement.removeEventListener("touchend",this.btouchendHandler),this.scrollerElement.removeEventListener("touchstart",this.btouchstartHandler),this.scrollerElement.replaceChildren(),this.scrollerElement.remove()}}export{c as DivinaScrolledPresenter};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Page as r,ReadingProgression as o}from"@readium/shared";import{Orientation as n,Spread as d}from"../epub/fxl/FXLSpreader.js";class f{constructor(t,e){this.page=r.center,this.addBlank=!1,this.link=t,this.index=e;const s=t.properties?.otherProperties.orientation;this.isLandscape=s===n.landscape||s!==n.portrait&&(t.width||0)>(t.height||0)}get number(){return this.index+1}get authoredPage(){return this.link.properties?.page}get double(){return this.page===r.center||this.isLandscape||this.addBlank}}class u{constructor(t){this.shift=!0,this.pages=[],this.spreads=[],this.itemToSlotArr=[],this.slotToItemArr=[],this.spreadOfItemArr=[],this.rtl=t.metadata.effectiveReadingProgression===o.rtl,this.pages=t.readingOrder.items.map((e,s)=>new f(e,s)),this.index(),this.testShift(),this.buildSlots()}index(t=!1){let e=0;this.pages.forEach((s,i)=>{!s.authoredPage||t?s.page=s.isLandscape?r.center:((this.shift?0:1)+i-e)%2?this.rtl?r.right:r.left:this.rtl?r.left:r.right:s.page=s.authoredPage,s.double&&e++}),this.buildSpreads()}testShift(){let t=!1;this.spreads.forEach((e,s)=>{if(e.length>1){t=!1;return}const i=e[0];s===0&&(i.isLandscape||i.link.properties?.otherProperties.spread===d.both)&&(this.shift=!1),t&&i.page===r.center&&(this.spreads[s-1][0].addBlank=!0),!i.isLandscape&&i.page!==r.center&&i.index>0?t=!0:t=!1}),this.shift||(this.spreads=[],this.index(!0))}buildSpreads(){this.spreads=[];let t=[];this.pages.forEach((e,s)=>{!s&&this.shift?this.spreads.push([e]):e.page===r.center?(t.length>0&&this.spreads.push(t),this.spreads.push([e]),t=[]):t.length>=2?(this.spreads.push(t),t=[e]):t.push(e)}),t.length>0&&this.spreads.push(t)}buildSlots(){this.itemToSlotArr=new Array(this.pages.length),this.slotToItemArr=[],this.spreadOfItemArr=new Array(this.pages.length);let t=0;this.spreads.forEach((e,s)=>{e.forEach(i=>{this.itemToSlotArr[i.index]=t,this.spreadOfItemArr[i.index]=s;const a=e.length===1?2:1;for(let h=0;h<a;h++)this.slotToItemArr[t+h]=i.index;t+=a})})}get slotCount(){return this.slotToItemArr.length}get nDouble(){return this.pages.reduce((t,e)=>t+(e.double?1:0),0)}slotOfItem(t){return this.itemToSlotArr[Math.max(0,Math.min(t,this.pages.length-1))]??0}itemOfSlot(t){return this.slotToItemArr[Math.max(0,Math.min(t,this.slotToItemArr.length-1))]??0}spreadIndexOfItem(t){return this.spreadOfItemArr[Math.max(0,Math.min(t,this.pages.length-1))]??0}spreadOfItem(t){return this.spreads[this.spreadIndexOfItem(t)]}isDouble(t){return this.spreadOfItem(t)?.length===1}findByHref(t){return this.pages.find(e=>e.link.href===t)}spreadPosition(t,e,s){return s<2||t.length<2?r.center:e===t[0]?this.rtl?r.right:r.left:this.rtl?r.left:r.right}}export{f as DivinaPage,u as DivinaSpreader};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sML as f}from"@readium/helpers";var g=(t=>(t.auto="auto",t.low="low",t.high="high",t.max="max",t))(g||{});const d=2560,l=1800,u=16;function m(t){const n=t.alternates?.items?[...t.alternates.items]:[];return n.unshift(t),n.filter(i=>!i.type||i.type.startsWith("image/"))}function O(t,n){const i=e=>(n.axis==="width"?e.width:e.height)||0,h=m(t).filter(e=>i(e)>0);if(h.length<=1)return h[0]||t;const r=h.sort((e,a)=>i(e)-i(a)),o=f.OS.iOS||f.OS.Android?n.axis==="width"?l:d:1/0,c=e=>{if(i(e)<=o)return e;const a=r.filter(s=>s===e||i(s)<=o);return a.length>1?a[a.length-2]:r[0]};switch(n.quality){case"low":return r[0];case"max":return c(r[r.length-1]);default:{const e=Math.min(n.axis==="width"?n.targetWidth:n.targetHeight,o);let a=r.find(s=>i(s)>=e-u)||r[r.length-1];if(n.quality==="high"){const s=r[r.indexOf(a)+1];s&&(a=s)}return c(a)}}}export{g as DivinaQuality,d as MOBILE_MAX_HEIGHT,l as MOBILE_MAX_WIDTH,m as gatherVariants,O as selectVariant};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ensureString as t,ensureNonNegative as o,ensureEnumValue as s,ensureBoolean as i,ensureValueInRange as e}from"../../preferences/guards.js";import{DivinaQuality as n}from"../DivinaVariantSelector.js";import{stripWidthRangeConfig as a}from"./DivinaPreferences.js";class p{constructor(r){this.backgroundColor=t(r.backgroundColor)||null,this.constraint=o(r.constraint)||0,this.quality=s(r.quality,n)||n.auto,this.scrolled=i(r.scrolled)??null,this.spreads=i(r.spreads)??!0,this.stripWidth=e(r.stripWidth,a.range)||720}}export{p as DivinaDefaults};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DivinaQuality as n}from"../DivinaVariantSelector.js";import{ensureString as o,ensureNonNegative as a,ensureEnumValue as l,ensureBoolean as e,ensureValueInRange as u}from"../../preferences/guards.js";const c={range:[480,2400],step:20};class i{constructor(t={}){this.backgroundColor=o(t.backgroundColor),this.constraint=a(t.constraint),this.quality=l(t.quality,n),this.scrolled=e(t.scrolled),this.spreads=e(t.spreads),this.stripWidth=u(t.stripWidth,c.range)}static serialize(t){const{...r}=t;return JSON.stringify(r)}static deserialize(t){try{const r=JSON.parse(t);return new i(r)}catch(r){return console.error("Failed to deserialize preferences:",r),null}}merging(t){const r={...this};for(const s of Object.keys(t))t[s]!==void 0&&(r[s]=t[s]);return new i(r)}}export{i as DivinaPreferences,c as stripWidthRangeConfig};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Layout as a}from"@readium/shared";import{Preference as u,EnumPreference as o,BooleanPreference as i,RangePreference as c}from"../../preferences/Preference.js";import{DivinaQuality as t}from"../DivinaVariantSelector.js";import{DivinaPreferences as s,stripWidthRangeConfig as n}from"./DivinaPreferences.js";class m{constructor(e,r,l){this.preferences=new s({...e}),this.settings=r,this.metadata=l}clear(){this.preferences=new s({backgroundColor:null,constraint:null,quality:null,scrolled:null,spreads:null,stripWidth:null})}updatePreference(e,r){this.preferences[e]=r}get manifestScrolled(){return this.metadata.effectiveLayout===a.scrolled}get backgroundColor(){return new u({initialValue:this.preferences.backgroundColor,effectiveValue:this.settings.backgroundColor,isEffective:!0,onChange:e=>{this.updatePreference("backgroundColor",e??null)}})}get quality(){return new o({initialValue:this.preferences.quality,effectiveValue:this.settings.quality,isEffective:!0,onChange:e=>{this.updatePreference("quality",e??null)},supportedValues:[t.auto,t.low,t.high,t.max]})}get scrolled(){return new i({initialValue:this.preferences.scrolled,effectiveValue:this.settings.scrolled,isEffective:!this.manifestScrolled,onChange:e=>{this.updatePreference("scrolled",e??null)}})}get spreads(){return new i({initialValue:this.preferences.spreads,effectiveValue:this.settings.spreads,isEffective:!this.settings.scrolled,onChange:e=>{this.updatePreference("spreads",e??null)}})}get stripWidth(){return new c({initialValue:this.preferences.stripWidth,effectiveValue:this.settings.stripWidth,isEffective:this.settings.scrolled,onChange:e=>{this.updatePreference("stripWidth",e??null)},supportedRange:n.range,step:n.step})}}export{m as DivinaPreferencesEditor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class r{constructor(t,i,o){this.backgroundColor=t.backgroundColor??i.backgroundColor,this.constraint=t.constraint??i.constraint,this.quality=t.quality??i.quality,this.scrolled=o?!0:t.scrolled??i.scrolled??!1,this.spreads=t.spreads??i.spreads,this.stripWidth=t.stripWidth??i.stripWidth}}export{r as DivinaSettings};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{NavigatorProtector as e}from"../../protection/NavigatorProtector.js";import{DragAndDropProtector as c}from"../../protection/DragAndDropProtector.js";import{CopyProtector as i}from"../../protection/CopyProtector.js";class y extends e{constructor(t={}){super(t),t.disableDragAndDrop&&(this.dragAndDropProtector=new c({onDragDetected:r=>{this.dispatchSuspiciousActivity("drag_detected",{dataTransferTypes:r,targetFrameSrc:""})},onDropDetected:(r,o)=>{this.dispatchSuspiciousActivity("drop_detected",{dataTransferTypes:r,fileCount:o,targetFrameSrc:""})}})),t.protectCopy&&(this.copyProtector=new i({onCopyBlocked:()=>{this.dispatchSuspiciousActivity("bulk_copy",{targetFrameSrc:""})}}))}destroy(){super.destroy(),this.dragAndDropProtector?.destroy(),this.copyProtector?.destroy()}}export{y as DivinaNavigatorProtector};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Layout as d,Profile as E,Link as _,ReadingProgression as g,Locator as v,LocatorText as D,getCssSelector as O,getHtmlId as I}from"@readium/shared";import{VisualNavigator as F}from"../Navigator.js";import{FramePoolManager as T}from"./frame/FramePoolManager.js";import{FXLFramePoolManager as A}from"./fxl/FXLFramePoolManager.js";import{ModuleLibrary as R,FXLModules as M,ReflowableModules as H}from"@readium/navigator-html-injectables";import{p as y}from"../_virtual/index.js";import{FrameManager as z}from"./frame/FrameManager.js";import{EpubPreferences as V}from"./preferences/EpubPreferences.js";import{EpubDefaults as N}from"./preferences/EpubDefaults.js";import{EpubPreferencesEditor as b}from"./preferences/EpubPreferencesEditor.js";import{ReadiumCSS as W}from"./css/ReadiumCSS.js";import{UserProperties as j,RSProperties as B}from"./css/Properties.js";import{getContentWidth as K}from"../helpers/dimensions.js";import{Injector as $}from"../injection/Injector.js";import{createReadiumEpubRules as G}from"../injection/epubInjectables.js";import{NavigatorProtector as X,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as S}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as J,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as x}from"../peripherals/KeyboardPeripherals.js";import{getScriptMode as w}from"../helpers/scriptMode.js";import{EpubSettings as C}from"./preferences/EpubSettings.js";import{LineLengths as U}from"../helpers/lineLength.js";import{supportsDecorationStyle as q,decorationsEqual as Y,resolveDecorationForWire as P}from"@readium/decorator";const Q=p=>({frameLoaded:p.frameLoaded||(()=>{}),positionChanged:p.positionChanged||(()=>{}),timelineItemChanged:p.timelineItemChanged||(()=>{}),tap:p.tap||(()=>!1),click:p.click||(()=>!1),zoom:p.zoom||(()=>{}),miscPointer:p.miscPointer||(()=>{}),scroll:p.scroll||(()=>{}),customEvent:p.customEvent||(()=>{}),handleLocator:p.handleLocator||(()=>!1),textSelected:p.textSelected||(()=>{}),contentProtection:p.contentProtection||(()=>{}),contextMenu:p.contextMenu||(()=>{}),peripheral:p.peripheral||(()=>{})});function Z(p,e){return p.length===e.length&&p.every((t,i)=>t===e[i])}class k extends F{constructor(e,t,i,s=[],r=void 0,o={preferences:{},defaults:{}}){super(),this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._timelineAugmented=!1,this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this.reflowViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=Q(i),this.currentLocation=r,s.length&&(this.positions=s),this._preferences=new V(o.preferences),this._defaults=new N(o.defaults),this._settings=new C(this._preferences,this._defaults);const h=w(t.metadata),f=h==="cjk-horizontal",a=h==="cjk-vertical",c=a||h==="mongolian-vertical",l=f||a;this._css=new W({rsProperties:new B({noVerticalPagination:c||void 0}),userProperties:new j({}),lineLengths:new U({optimalChars:this._settings.optimalLineLength,minChars:this._settings.minimalLineLength,maxChars:this._settings.maximalLineLength,padding:this._settings.scroll?(this._settings.scrollPaddingLeft||0)+(this._settings.scrollPaddingRight||0):(this._settings.pageGutter||0)*2,fontFace:this._settings.fontFamily,letterSpacing:this._settings.letterSpacing,wordSpacing:this._settings.wordSpacing,isCJK:l}),container:e,constraint:this._settings.constraint,isCJKVertical:c}),this._layout=k.determineLayout(t,!!this._settings.scroll),this.currentProgression=t.metadata.effectiveReadingProgression,this._injectablesConfig=o.injectables||{rules:[],allowedDomains:[]},this._readiumRulesPromise=G(t.metadata,t.readingOrder.items),this._contentProtection=o.contentProtection||{},this._decoratorConfig=o.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,o.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new X(this._contentProtection),this._suspiciousActivityListener=u=>{const{type:m,...L}=u.detail;m==="context_menu"?this.listeners.contextMenu(L):this.listeners.contentProtection(m,L)},window.addEventListener(S,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new J({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=u=>{const m=u.detail;this.listeners.peripheral(m)},window.addEventListener(x,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(async()=>await this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}static determineLayout(e,t){const i=e.metadata.effectiveLayout;if(i===d.fixed)return d.fixed;if(e.metadata.otherMetadata&&"http://openmangaformat.org/schema/1.0#version"in e.metadata.otherMetadata)return d.fixed;if(e.metadata?.conformsTo?.includes(E.DIVINA))return d.fixed;if(i===d.scrolled)return d.scrolled;const s=w(e.metadata);return s==="cjk-vertical"||s==="mongolian-vertical"?d.scrolled:i===d.reflowable&&t?d.scrolled:d.reflowable}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),!this._injector){const e=await this._readiumRulesPromise;this._injector=new $({rules:[...e,...this._injectablesConfig.rules],allowedDomains:this._injectablesConfig.allowedDomains})}if(this._layout===d.fixed)this.framePool=new A(this.container,this.positions,this.pub,this._injector,this._contentProtection,this._keyboardPeripherals,[...this._decorationResizeSelectors]),this.framePool.listener=(e,t)=>{this.eventListener(e,t)};else{await this.updateCSS(!1);const e=this.compileCSSProperties(this._css);this.framePool=new T(this.container,this.positions,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const s=i.indexOf("#");return s>=0?i.slice(s+1):""}).filter(Boolean),[...this._decorationResizeSelectors])}this.currentLocation===void 0&&(this.currentLocation=this.positions[0]),await this.resizeHandler(),await this.apply()}get settings(){if(this._layout===d.fixed)return Object.freeze({...this._settings});{const e=this._css.userProperties.colCount||this._css.rsProperties.colCount||this._settings.columnCount;return Object.freeze({...this._settings,columnCount:e})}}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){const e=this._settings;this._settings=new C(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._layout===d.fixed?this.handleFXLPrefs(e,this._settings):await this.updateCSS(!0)}handleFXLPrefs(e,t){e.columnCount!==t.columnCount&&this.framePool.setPerPage(t.columnCount)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,s]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=s;for(const[i,s]of Object.entries(e.userProperties.toCSSProperties()))t[i]=s;return t}async commitCSS(e){if(!this.framePool)return;const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t),this._css.userProperties.view==="paged"&&this._layout===d.scrolled?await this.setLayout(d.reflowable):this._css.userProperties.view==="scroll"&&this._layout===d.reflowable&&await this.setLayout(d.scrolled),this._css.setContainerWidth()}async resizeHandler(){const e=this.container.parentElement||document.documentElement;if(this._layout===d.fixed){if(this.container.style.width=`${K(e)-this._settings.constraint}px`,!this.framePool)return;this.framePool.resizeHandler()}else{const t=this._css.userProperties.colCount,i=this._css.userProperties.lineLength;this._css.resizeHandler(),(this._css.userProperties.view!=="scroll"&&t!==this._css.userProperties.colCount||i!==this._css.userProperties.lineLength)&&await this.commitCSS(this._css)}}get layout(){return this._layout}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get _cframes(){return(this.framePool?.currentFrames??[]).filter(e=>!(e instanceof z&&e.isDestroyed))}get pool(){return this.framePool}eventListener(e,t,i){switch(e){case"_pong":if(this.listeners.frameLoaded(this._cframes[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i){const n=this._cframes.filter(l=>!!l).indexOf(i),c=n>=0?this.viewport.readingOrder[n]:void 0;c&&this._reapplyDecorationsToFrame(i,c)}else this._reapplyDecorationsToCurrentFrames();break;case"first_visible_locator":const s=v.deserialize(t);if(!s)break;this.currentLocation=new v({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:s?.locations,text:s?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const a=t;if(i){const c=this._cframes.filter(u=>!!u).indexOf(i),l=c>=0?this.viewport.readingOrder[c]:void 0;if(l){const u=this.pub.readingOrder.findWithHref(l);a.locator=new v({href:l,type:u.type||"application/xhtml+xml",text:new D({highlight:a.text})})}}this.listeners.textSelected(a);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const r=t;if(r.interactiveElement){const a=new DOMParser().parseFromString(r.interactiveElement,"text/html").body.children[0];if(a.nodeType===a.ELEMENT_NODE&&a.nodeName==="A"&&a.hasAttribute("href")){const n=a.attributes.getNamedItem("href")?.value;if(n.startsWith("#"))this.go(this.currentLocation.copyWithLocations({fragments:[n.substring(1)]}),!1,()=>{});else if(n.startsWith("http://")||n.startsWith("https://")||n.startsWith("mailto:")||n.startsWith("tel:"))this.listeners.handleLocator(new _({href:n}).locator);else try{this.goLink(new _({href:y.join(y.dirname(this.currentLocation.href),n)}),!1,()=>{})}catch(c){console.warn(`Couldn't go to link for ${n}: ${c}`),this.listeners.handleLocator(new _({href:n}).locator)}}else console.log("Clicked on",a)}else{if(this._layout===d.fixed&&this.framePool.doNotDisturb&&(r.doNotDisturb=!0),this._layout===d.fixed&&(this.currentProgression===g.rtl||this.currentProgression===g.ltr)&&this.framePool.currentFrames.length>1){const c=this.framePool.currentFrames;r.targetFrameSrc===c[this.currentProgression===g.rtl?0:1]?.source&&(r.x+=(c[this.currentProgression===g.rtl?1:0]?.iframe.contentWindow?.innerWidth??0)*window.devicePixelRatio)}if(e==="click"?this.listeners.click(r):this.listeners.tap(r))break;const n=(this._cframes.length===2?this._cframes[0].window.innerWidth+this._cframes[1].window.innerWidth:this._cframes[0].window.innerWidth)*window.devicePixelRatio/4;r.x>=n&&r.x<=n*3&&this.listeners.miscPointer(1),r.x<n?this.goLeft(!1,()=>{}):r.x>n*3&&this.goRight(!1,()=>{})}break;case"tap_more":this.listeners.miscPointer(t);break;case"no_more":this.changeResource(1);break;case"no_less":this.changeResource(-1);break;case"swipe":break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":this.syncLocation(t);break;case"content_protection":const o=t;this.listeners.contentProtection(o.type,o);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const h=t,f={...h,interactiveElement:void 0};h.interactiveElement&&(f.interactiveElement=new DOMParser().parseFromString(h.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(f);break;case"log":console.log(this._cframes[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){let e=Array.from(R.keys());if(this._layout===d.fixed)return e.filter(s=>M.includes(s));e=e.filter(s=>H.includes(s));const t=w(this.pub.metadata);if(t==="cjk-vertical"||t==="mongolian-vertical")return e.filter(s=>s!=="column_snapper"&&s!=="scroll_snapper");const i=e;return this._layout===d.scrolled?e=i.filter(s=>s!=="column_snapper"&&s!=="cjk_vertical_snapper"):e=i.filter(s=>s!=="scroll_snapper"&&s!=="cjk_vertical_snapper"),e}attachListener(){const e=this._cframes.filter(t=>!!t);if(e.length===0)throw Error("no cframe to attach listener to");e.forEach(t=>{t.msg&&(t.msg.listener=(i,s)=>{this.eventListener(i,s,t)})}),this._reapplyDecorationsToCurrentFrames()}async apply(){if(await this.framePool.update(this.pub,this.currentLocator,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}supportsDecorationStyle(e){return q(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivationToFrames(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverToFrames(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const s=[...t].some(o=>o.onDecorationActivated);this._decorationActivationState.has(i)&&!s&&(this._decorationActivationState.delete(i),this._sendDecorationActivationToFrames(i,!1));const r=[...t].some(o=>o.onDecorationPointerEnter||o.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!r&&(this._decorationHoverState.delete(i),this._sendDecorationHoverToFrames(i,!1))})}_sendDecorationActivationToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_activatable",{group:e,activatable:t})})}_sendDecorationHoverToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_hoverable",{group:e,hoverable:t})})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],s=new Map(i.map(c=>[c.id,c])),r=new Map(e.map(c=>[c.id,c])),o=[],h=[],f=[];for(const[c,l]of s)r.has(c)?Y(l,r.get(c))||f.push(r.get(c)):o.push(c);for(const[c,l]of r)s.has(c)||h.push(l);this._decorations.set(t,e),this._sendDecorationOps(t,o,h,f,i);const a=this._decorationActivationState.get(t);a!==void 0&&this._sendDecorationActivationToFrames(t,a);const n=this._decorationHoverState.get(t);n!==void 0&&this._sendDecorationHoverToFrames(t,n)}_sendDecorationOps(e,t,i,s,r){const o=this._cframes.filter(a=>!!a),h=new Map(r.map(a=>[a.id,a])),f=this.viewport.readingOrder;o.forEach((a,n)=>{if(!a.msg)return;const c=f[n];if(c){for(const l of t){const u=h.get(l);!u||u.locator.href!==c||a.msg.send("decorate",{group:e,action:"remove",decoration:{id:l}})}for(const l of i)l.locator.href===c&&a.msg.send("decorate",{group:e,action:"add",decoration:P(l,this._decoratorConfig.decorationTemplates)});for(const l of s)l.locator.href===c&&a.msg.send("decorate",{group:e,action:"update",decoration:P(l,this._decoratorConfig.decorationTemplates)})}})}_reapplyDecorationsToFrame(e,t){if(e.msg){for(const[i,s]of this._decorations){const r=s.filter(o=>o.locator.href===t);if(r.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const o of r)e.msg.send("decorate",{group:i,action:"add",decoration:P(o,this._decoratorConfig.decorationTemplates)})}}for(const[i,s]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:s});for(const[i,s]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:s})}}_reapplyDecorationsToCurrentFrames(){const e=this._cframes.filter(i=>!!i),t=this.viewport.readingOrder;e.forEach((i,s)=>{const r=t[s];r&&this._reapplyDecorationsToFrame(i,r)})}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return!1;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};let r=!1;for(const o of t)o.onDecorationActivated?.(s)&&(r=!0);return r}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(r=>r.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const r of t)r.onDecorationPointerEnter?.(s)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(r=>r.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const r of t)r.onDecorationPointerLeave?.(s)}async destroy(){this._suspiciousActivityListener&&window.removeEventListener(S,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(x,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}async changeResource(e){if(e===0)return!1;if(this._layout===d.fixed){const s=this.framePool,r=s.viewport.positions[0];if(e===1){if(!s.next(s.perPage))return!1}else if(e===-1){if(!s.prev(s.perPage))return!1}else throw Error("Invalid relative value for FXL");const o=s.viewport.positions[0];if(r>o){for(let h=this.positions.length-1;h>=0;h--)if(this.positions[h].href===this.pub.readingOrder.items[o-1].href){this.currentLocation=this.positions[h].copyWithLocations({progression:.999999999999});break}}else if(r<o){for(let h=0;h<this.positions.length;h++)if(this.positions[h].href===this.pub.readingOrder.items[o-1].href){this.currentLocation=this.positions[h];break}}return await this.apply(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0}const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));if(i===t)return this._cframes[0]?.msg?.send("shake",void 0,async s=>{}),!1;if(t>i){for(let s=this.positions.length-1;s>=0;s--)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s].copyWithLocations({progression:.999999999999});break}}else for(let s=0;s<this.positions.length;s++)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s];break}return await this.apply(),!0}findLastPositionInProgressionRange(e,t){const i=e.findLastIndex(s=>{const r=s.locations.progression;return!!(r&&r>t.start&&r<=t.end)});return i!==-1?e[i]:void 0}findNearestPositions(e){const t=this.positions.filter(o=>o.href===this.currentLocation.href);let i=this.currentLocation,s;const r=t.findLastIndex(o=>(o.locations.progression??0)<=e.start);if(r!==-1){i=t[r];const o=t.slice(r+1);s=this.findLastPositionInProgressionRange(o,e)}return{first:i,last:s}}updateViewport(e){this.reflowViewport.readingOrder=[],this.reflowViewport.progressions.clear(),this.reflowViewport.positions=null,this.currentLocation&&(this.reflowViewport.readingOrder.push(this.currentLocation.href),this.reflowViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.reflowViewport.positions=[this.currentLocation.locations.position],this.lastLocationInView?.locations?.position!==void 0&&this.reflowViewport.positions.push(this.lastLocationInView.locations.position)))}async syncLocation(e){const t=e,i=this.findNearestPositions(t);this.currentLocation=i.first.copyWithLocations({progression:t.start}),this.lastLocationInView=i.last,this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const s=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(s),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_prev",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(-1);this._isNavigating=!1,t(s)}})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_next",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(1);this._isNavigating=!1,t(s)}})}get currentLocator(){return this.currentLocation}get viewport(){return this._layout===d.fixed?this.framePool?this.framePool.viewport:{readingOrder:[],progressions:new Map,positions:null}:this.reflowViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.currentProgression}async setLayout(e){this._layout!==e&&(this._layout=e,await this.framePool.update(this.pub,this.currentLocator,this.determineModules(),!0),this.attachListener())}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((s,r)=>{if(s.children?.length)return{};const o=r.href.indexOf("#"),h=o>=0?r.href.slice(0,o):r.href,f=o>=0?r.href.slice(o+1):void 0,a=t.filter(l=>l.href===h);if(!a.length)return{};const n=f?a.find(l=>l.locations.fragments[0]===f):void 0;let c;return n?c=n:i.has(h)?c=void 0:(i.add(h),c=a.reduce((l,u)=>(u.locations.position??1/0)<(l.locations.position??1/0)?u:l)),c?{position:c.locations.position,scroll:n?.locations.progression}:{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const s=Reflect.get(t,i,t);return typeof s=="function"?s.bind(t):s}return s=>{const r=this._visibleFragmentIds;let o=(r.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${r[0]}`]})):void 0)??s;const h=(r.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${r[r.length-1]}`]})):void 0)??s;if(this.isScrollStart){const n=t.ancestors(o).find(c=>c.references.includes(this.currentLocation.href));n&&(o=n)}const f=t.navigableFrom(o).previous,a=t.navigableFrom(h).next;return{previous:f,next:a}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,s=O(e.locations);if(e.text?.highlight?i=await new Promise((f,a)=>{this._cframes[0].msg.send("go_text",s?[e.text?.serialize(),s]:e.text?.serialize(),n=>f(n))}):s&&(i=await new Promise((f,a)=>{this._cframes[0].msg.send("go_text",["",s],n=>f(n))})),i){t(i);return}const r=I(e.locations);if(r&&(i=await new Promise((f,a)=>{this._cframes[0].msg.send("go_id",r,n=>f(n))})),i){t(i);return}const o=e?.locations?.progression;o&&o>0?i=await new Promise((f,a)=>{this._cframes[0].msg.send("go_progression",o,n=>f(n))}):i=!0,t(i)}go(e,t,i){const s=e.href.split("#")[0];let r=this.pub.readingOrder.findWithHref(s);if(!r)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.positions.find(o=>o.href===r.href),this.apply().then(()=>this.loadLocator(e,o=>{this._isNavigating=!1,i(o)})).then(()=>{this.attachListener()})}goLink(e,t,i){return this.go(e.locator,t,i)}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!Z(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}export{k as EpubNavigator};
|
|
1
|
+
import{Layout as d,Profile as E,Link as _,ReadingProgression as m,Locator as v,LocatorText as D,getCssSelector as O,getHtmlId as I}from"@readium/shared";import{VisualNavigator as F}from"../Navigator.js";import{FramePoolManager as R}from"./frame/FramePoolManager.js";import{FXLFramePoolManager as T}from"./fxl/FXLFramePoolManager.js";import{ModuleLibrary as M,FXLModules as A,ReflowableModules as H}from"@readium/navigator-html-injectables";import{p as L}from"../_virtual/index.js";import{isTypedOMSupported as z}from"./fxl/FXLPeripherals.js";import{FrameManager as V}from"./frame/FrameManager.js";import{EpubPreferences as W}from"./preferences/EpubPreferences.js";import{EpubDefaults as N}from"./preferences/EpubDefaults.js";import{EpubPreferencesEditor as b}from"./preferences/EpubPreferencesEditor.js";import{ReadiumCSS as j}from"./css/ReadiumCSS.js";import{UserProperties as B,RSProperties as K}from"./css/Properties.js";import{getContentWidth as q}from"../helpers/dimensions.js";import{Injector as $}from"../injection/Injector.js";import{createReadiumEpubRules as G}from"../injection/epubInjectables.js";import{NavigatorProtector as X,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as S}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as J,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as x}from"../peripherals/KeyboardPeripherals.js";import{getScriptMode as w}from"../helpers/scriptMode.js";import{EpubSettings as C}from"./preferences/EpubSettings.js";import{LineLengths as U}from"../helpers/lineLength.js";import{supportsDecorationStyle as Y,decorationsEqual as Q,resolveDecorationForWire as P}from"@readium/decorator";const Z=p=>({frameLoaded:p.frameLoaded||(()=>{}),positionChanged:p.positionChanged||(()=>{}),timelineItemChanged:p.timelineItemChanged||(()=>{}),tap:p.tap||(()=>!1),click:p.click||(()=>!1),zoom:p.zoom||(()=>{}),miscPointer:p.miscPointer||(()=>{}),scroll:p.scroll||(()=>{}),customEvent:p.customEvent||(()=>{}),handleLocator:p.handleLocator||(()=>!1),textSelected:p.textSelected||(()=>{}),contentProtection:p.contentProtection||(()=>{}),contextMenu:p.contextMenu||(()=>{}),peripheral:p.peripheral||(()=>{})});function ee(p,e){return p.length===e.length&&p.every((t,i)=>t===e[i])}class k extends F{constructor(e,t,i,s=[],o=void 0,r={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._timelineAugmented=!1,this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this.reflowViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=Z(i),this.currentLocation=o,s.length&&(this.positions=s),this._preferences=new W(r.preferences),this._defaults=new N(r.defaults),this._settings=new C(this._preferences,this._defaults);const h=w(t.metadata),f=h==="cjk-horizontal",n=h==="cjk-vertical",c=n||h==="mongolian-vertical",l=f||n;this._css=new j({rsProperties:new K({noVerticalPagination:c||void 0}),userProperties:new B({}),lineLengths:new U({optimalChars:this._settings.optimalLineLength,minChars:this._settings.minimalLineLength,maxChars:this._settings.maximalLineLength,padding:this._settings.scroll?(this._settings.scrollPaddingLeft||0)+(this._settings.scrollPaddingRight||0):(this._settings.pageGutter||0)*2,fontFace:this._settings.fontFamily,letterSpacing:this._settings.letterSpacing,wordSpacing:this._settings.wordSpacing,isCJK:l}),container:e,constraint:this._settings.constraint,isCJKVertical:c}),this._layout=k.determineLayout(t,!!this._settings.scroll),this.currentProgression=t.metadata.effectiveReadingProgression,this._injectablesConfig=r.injectables||{rules:[],allowedDomains:[]},this._readiumRulesPromise=G(t.metadata,t.readingOrder.items),this._contentProtection=r.contentProtection||{},this._decoratorConfig=r.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._upgradeInsecureRequests=r.upgradeInsecureRequests??"always",this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,r.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new X(this._contentProtection),this._suspiciousActivityListener=u=>{const{type:g,...y}=u.detail;g==="context_menu"?this.listeners.contextMenu(y):this.listeners.contentProtection(g,y)},window.addEventListener(S,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new J({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=u=>{const g=u.detail;this.listeners.peripheral(g)},window.addEventListener(x,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(async()=>await this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}static determineLayout(e,t){const i=e.metadata.effectiveLayout;if(i===d.fixed)return d.fixed;if(e.metadata.otherMetadata&&"http://openmangaformat.org/schema/1.0#version"in e.metadata.otherMetadata)return d.fixed;if(e.metadata?.conformsTo?.includes(E.DIVINA))return d.fixed;if(i===d.scrolled)return d.scrolled;const s=w(e.metadata);return s==="cjk-vertical"||s==="mongolian-vertical"?d.scrolled:i===d.reflowable&&t?d.scrolled:d.reflowable}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),!this._injector){const e=await this._readiumRulesPromise;this._injector=new $({rules:[...e,...this._injectablesConfig.rules],allowedDomains:this._injectablesConfig.allowedDomains})}if(!this._destroyed){if(this._layout===d.fixed)this.framePool=new T(this.container,this.positions,this.pub,this._layout,this._injector,this._contentProtection,this._keyboardPeripherals,[...this._decorationResizeSelectors],this._upgradeInsecureRequests),this.framePool.listener=(e,t)=>{this.eventListener(e,t)};else{if(await this.updateCSS(!1),this._destroyed)return;const e=this.compileCSSProperties(this._css);this.framePool=new R(this.container,this.positions,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const s=i.indexOf("#");return s>=0?i.slice(s+1):""}).filter(Boolean),[...this._decorationResizeSelectors],this._upgradeInsecureRequests)}if(this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),await this.resizeHandler(),!this._destroyed)return new Promise(e=>{if(this._destroyed)return e(!1);this.go(this.currentLocation,!1,e)})}}get settings(){if(this._layout===d.fixed)return Object.freeze({...this._settings});{const e=this._css.userProperties.colCount||this._css.rsProperties.colCount||this._settings.columnCount;return Object.freeze({...this._settings,columnCount:e})}}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){const e=this._settings;this._settings=new C(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._layout===d.fixed?this.handleFXLPrefs(e,this._settings):await this.updateCSS(!0)}handleFXLPrefs(e,t){e.columnCount!==t.columnCount&&this.framePool.setPerPage(t.columnCount)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,s]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=s;for(const[i,s]of Object.entries(e.userProperties.toCSSProperties()))t[i]=s;return t}async commitCSS(e){if(!this.framePool)return;const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t),this._css.userProperties.view==="paged"&&this._layout===d.scrolled?await this.setLayout(d.reflowable):this._css.userProperties.view==="scroll"&&this._layout===d.reflowable&&await this.setLayout(d.scrolled),this._css.setContainerWidth()}async resizeHandler(){const e=this.container.parentElement||document.documentElement;if(this._layout===d.fixed){const t=q(e)-this._settings.constraint;if(z()?this.container.attributeStyleMap.set("width",CSS.px(t)):this.container.style.width=`${t}px`,!this.framePool)return;this.framePool.resizeHandler()}else{const t=this._css.userProperties.colCount,i=this._css.userProperties.lineLength;this._css.resizeHandler(),(this._css.userProperties.view!=="scroll"&&t!==this._css.userProperties.colCount||i!==this._css.userProperties.lineLength)&&await this.commitCSS(this._css)}}get layout(){return this._layout}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get _cframes(){return(this.framePool?.currentFrames??[]).filter(e=>!(e instanceof V&&e.isDestroyed))}get pool(){return this.framePool}eventListener(e,t,i){switch(e){case"_pong":if(this.listeners.frameLoaded(this._cframes[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i){const a=this._cframes.filter(l=>!!l).indexOf(i),c=a>=0?this.viewport.readingOrder[a]:void 0;c&&this._reapplyDecorationsToFrame(i,c)}else this._reapplyDecorationsToCurrentFrames();break;case"first_visible_locator":const s=v.deserialize(t);if(!s)break;this.currentLocation=new v({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:s?.locations,text:s?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const n=t;if(i){const c=this._cframes.filter(u=>!!u).indexOf(i),l=c>=0?this.viewport.readingOrder[c]:void 0;if(l){const u=this.pub.readingOrder.findWithHref(l);n.locator=new v({href:l,type:u.type||"application/xhtml+xml",text:new D({highlight:n.text})})}}this.listeners.textSelected(n);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const o=t;if(o.interactiveElement){const n=new DOMParser().parseFromString(o.interactiveElement,"text/html").body.children[0];if(n.nodeType===n.ELEMENT_NODE&&n.nodeName==="A"&&n.hasAttribute("href")){const a=n.attributes.getNamedItem("href")?.value;if(a.startsWith("#"))this.go(this.currentLocation.copyWithLocations({fragments:[a.substring(1)]}),!1,()=>{});else if(a.startsWith("http://")||a.startsWith("https://")||a.startsWith("mailto:")||a.startsWith("tel:"))this.listeners.handleLocator(new _({href:a}).locator);else try{this.goLink(new _({href:L.join(L.dirname(this.currentLocation.href),a)}),!1,()=>{})}catch(c){console.warn(`Couldn't go to link for ${a}: ${c}`),this.listeners.handleLocator(new _({href:a}).locator)}}else console.log("Clicked on",n)}else{if(this._layout===d.fixed&&this.framePool.doNotDisturb&&(o.doNotDisturb=!0),this._layout===d.fixed&&(this.currentProgression===m.rtl||this.currentProgression===m.ltr)&&this.framePool.currentFrames.length>1){const c=this.framePool.currentFrames;o.targetFrameSrc===c[this.currentProgression===m.rtl?0:1]?.source&&(o.x+=(c[this.currentProgression===m.rtl?1:0]?.iframe.contentWindow?.innerWidth??0)*window.devicePixelRatio)}if(e==="click"?this.listeners.click(o):this.listeners.tap(o))break;const a=(this._cframes.length===2?this._cframes[0].window.innerWidth+this._cframes[1].window.innerWidth:this._cframes[0].window.innerWidth)*window.devicePixelRatio/4;o.x>=a&&o.x<=a*3&&this.listeners.miscPointer(1),o.x<a?this.goLeft(!1,()=>{}):o.x>a*3&&this.goRight(!1,()=>{})}break;case"tap_more":this.listeners.miscPointer(t);break;case"no_more":this.changeResource(1);break;case"no_less":this.changeResource(-1);break;case"swipe":break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":this.syncLocation(t);break;case"content_protection":const r=t;this.listeners.contentProtection(r.type,r);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const h=t,f={...h,interactiveElement:void 0};h.interactiveElement&&(f.interactiveElement=new DOMParser().parseFromString(h.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(f);break;case"log":console.log(this._cframes[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){let e=Array.from(M.keys());if(this._layout===d.fixed)return e.filter(s=>A.includes(s));e=e.filter(s=>H.includes(s));const t=w(this.pub.metadata);if(t==="cjk-vertical"||t==="mongolian-vertical")return e.filter(s=>s!=="column_snapper"&&s!=="scroll_snapper");const i=e;return this._layout===d.scrolled?e=i.filter(s=>s!=="column_snapper"&&s!=="cjk_vertical_snapper"):e=i.filter(s=>s!=="scroll_snapper"&&s!=="cjk_vertical_snapper"),e}attachListener(){const e=this._cframes.filter(t=>!!t);if(e.length===0)throw Error("no cframe to attach listener to");e.forEach(t=>{t.msg&&(t.msg.listener=(i,s)=>{this.eventListener(i,s,t)})}),this._reapplyDecorationsToCurrentFrames()}async apply(){if(await this.framePool.update(this.pub,this.currentLocator,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}supportsDecorationStyle(e){return Y(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivationToFrames(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverToFrames(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const s=[...t].some(r=>r.onDecorationActivated);this._decorationActivationState.has(i)&&!s&&(this._decorationActivationState.delete(i),this._sendDecorationActivationToFrames(i,!1));const o=[...t].some(r=>r.onDecorationPointerEnter||r.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!o&&(this._decorationHoverState.delete(i),this._sendDecorationHoverToFrames(i,!1))})}_sendDecorationActivationToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_activatable",{group:e,activatable:t})})}_sendDecorationHoverToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_hoverable",{group:e,hoverable:t})})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],s=new Map(i.map(c=>[c.id,c])),o=new Map(e.map(c=>[c.id,c])),r=[],h=[],f=[];for(const[c,l]of s)o.has(c)?Q(l,o.get(c))||f.push(o.get(c)):r.push(c);for(const[c,l]of o)s.has(c)||h.push(l);this._decorations.set(t,e),this._sendDecorationOps(t,r,h,f,i);const n=this._decorationActivationState.get(t);n!==void 0&&this._sendDecorationActivationToFrames(t,n);const a=this._decorationHoverState.get(t);a!==void 0&&this._sendDecorationHoverToFrames(t,a)}_sendDecorationOps(e,t,i,s,o){const r=this._cframes.filter(n=>!!n),h=new Map(o.map(n=>[n.id,n])),f=this.viewport.readingOrder;r.forEach((n,a)=>{if(!n.msg)return;const c=f[a];if(c){for(const l of t){const u=h.get(l);!u||u.locator.href!==c||n.msg.send("decorate",{group:e,action:"remove",decoration:{id:l}})}for(const l of i)l.locator.href===c&&n.msg.send("decorate",{group:e,action:"add",decoration:P(l,this._decoratorConfig.decorationTemplates)});for(const l of s)l.locator.href===c&&n.msg.send("decorate",{group:e,action:"update",decoration:P(l,this._decoratorConfig.decorationTemplates)})}})}_reapplyDecorationsToFrame(e,t){if(e.msg){for(const[i,s]of this._decorations){const o=s.filter(r=>r.locator.href===t);if(o.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const r of o)e.msg.send("decorate",{group:i,action:"add",decoration:P(r,this._decoratorConfig.decorationTemplates)})}}for(const[i,s]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:s});for(const[i,s]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:s})}}_reapplyDecorationsToCurrentFrames(){const e=this._cframes.filter(i=>!!i),t=this.viewport.readingOrder;e.forEach((i,s)=>{const o=t[s];o&&this._reapplyDecorationsToFrame(i,o)})}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(r=>r.id===e.decorationId);if(!i)return!1;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};let o=!1;for(const r of t)r.onDecorationActivated?.(s)&&(o=!0);return o}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerEnter?.(s)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerLeave?.(s)}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(S,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(x,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}async changeResource(e){if(e===0)return!1;if(this._layout===d.fixed){const s=this.framePool,o=s.viewport.positions[0];if(e===1){if(!s.next(s.perPage))return!1}else if(e===-1){if(!s.prev(s.perPage))return!1}else throw Error("Invalid relative value for FXL");const r=s.viewport.positions[0];if(o>r){for(let h=this.positions.length-1;h>=0;h--)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h].copyWithLocations({progression:.999999999999});break}}else if(o<r){for(let h=0;h<this.positions.length;h++)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h];break}}return await this.apply(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0}const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));if(i===t)return this._cframes[0]?.msg?.send("shake",void 0,async s=>{}),!1;if(t>i){for(let s=this.positions.length-1;s>=0;s--)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s].copyWithLocations({progression:.999999999999});break}}else for(let s=0;s<this.positions.length;s++)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s];break}return await this.apply(),!0}findLastPositionInProgressionRange(e,t){const i=e.findLastIndex(s=>{const o=s.locations.progression;return!!(o&&o>t.start&&o<=t.end)});return i!==-1?e[i]:void 0}findNearestPositions(e){const t=this.positions.filter(r=>r.href===this.currentLocation.href);let i=this.currentLocation,s;const o=t.findLastIndex(r=>(r.locations.progression??0)<=e.start);if(o!==-1){i=t[o];const r=t.slice(o+1);s=this.findLastPositionInProgressionRange(r,e)}return{first:i,last:s}}updateViewport(e){this.reflowViewport.readingOrder=[],this.reflowViewport.progressions.clear(),this.reflowViewport.positions=null,this.currentLocation&&(this.reflowViewport.readingOrder.push(this.currentLocation.href),this.reflowViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.reflowViewport.positions=[this.currentLocation.locations.position],this.lastLocationInView?.locations?.position!==void 0&&this.reflowViewport.positions.push(this.lastLocationInView.locations.position)))}async syncLocation(e){const t=e,i=this.findNearestPositions(t);this.currentLocation=i.first.copyWithLocations({progression:t.start}),this.lastLocationInView=i.last,this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const s=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(s),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_prev",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(-1);this._isNavigating=!1,t(s)}})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_next",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(1);this._isNavigating=!1,t(s)}})}get currentLocator(){return this.currentLocation}get viewport(){return this._layout===d.fixed?this.framePool?this.framePool.viewport:{readingOrder:[],progressions:new Map,positions:null}:this.reflowViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.currentProgression}async setLayout(e){this._layout!==e&&(this._layout=e,await this.framePool.update(this.pub,this.currentLocator,this.determineModules(),!0),this.attachListener())}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((s,o)=>{if(s.children?.length)return{};const r=o.href.indexOf("#"),h=r>=0?o.href.slice(0,r):o.href,f=r>=0?o.href.slice(r+1):void 0,n=t.filter(l=>l.href===h);if(!n.length)return{};const a=f?n.find(l=>l.locations.fragments?.[0]===f):void 0;let c;return a?c=a:i.has(h)?c=void 0:(i.add(h),c=n.reduce((l,u)=>(u.locations.position??1/0)<(l.locations.position??1/0)?u:l)),c?{position:c.locations.position,scroll:a?.locations.progression}:{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const s=Reflect.get(t,i,t);return typeof s=="function"?s.bind(t):s}return s=>{const o=this._visibleFragmentIds;let r=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[0]}`]})):void 0)??s;const h=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[o.length-1]}`]})):void 0)??s;if(this.isScrollStart){const a=t.ancestors(r).find(c=>c.references.includes(this.currentLocation.href));a&&(r=a)}const f=t.navigableFrom(r).previous,n=t.navigableFrom(h).next;return{previous:f,next:n}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,s=O(e.locations);if(e.text?.highlight?i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_text",s?[e.text?.serialize(),s]:e.text?.serialize(),a=>f(a))}):s&&(i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_text",["",s],a=>f(a))})),i){t(i);return}const o=I(e.locations);if(o&&(i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_id",o,a=>f(a))})),i){t(i);return}const r=e.locations?.progression;r&&r>0?i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_progression",r,a=>f(a))}):i=!0,t(i)}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(s=>s.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let s=0,o=1/0;for(let r=0;r<this.positions.length;r++){const f=this.positions[r].locations.totalProgression??r/this.positions.length,n=Math.abs(f-i);n<o&&(o=n,s=r)}e=this.positions[s].copyWithLocations(e.locations)}}return e}go(e,t,i){e=this.completeLocator(e);const s=e.href.split("#")[0];let o=this.pub.readingOrder.findWithHref(s);if(!o)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.positions.find(r=>r.href===o.href),this.apply().then(()=>this.loadLocator(e,r=>{this._isNavigating=!1,i(r)})).then(()=>{this.attachListener()}).catch(r=>{console.error(r),this._isNavigating=!1,i(!1)})}goLink(e,t,i){return this.go(e.locator,t,i)}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!ee(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}export{k as EpubNavigator};
|
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{MediaType as
|
|
1
|
+
import{MediaType as u,Link as f,ReadingProgression as y}from"@readium/shared";import{getScriptMode as w}from"../../helpers/scriptMode.js";const m=o=>o.split(/[?#]/)[0],R=o=>{const e=m(o);if(e.endsWith("/"))return e;try{const t=new URL(e);return t.pathname=t.pathname.substring(0,t.pathname.lastIndexOf("/")+1),t.href}catch{return e.replace(/[^/]*$/,"")}},L=(o,e="always",t)=>{const r=e==="always"||(e==="never"?!1:typeof t=="string"&&t.startsWith("https:")),i=o.join(" ");return[...r?["upgrade-insecure-requests"]:[],`default-src ${i} blob:`,"connect-src 'none'",`script-src ${i} blob: 'unsafe-inline'`,`style-src ${i} blob: 'unsafe-inline'`,`img-src ${i} blob: data:`,`font-src ${i} blob: data:`,`object-src ${i} blob:`,`child-src ${i}`,"form-action 'none'"].join("; ")};class v{constructor(e,t,r,i){this.pub=e,this.baseURL=t,this.item=r,this.injector=null,this.item=r,this.cssProperties=i.cssProperties,this.injector=i.injector??null,this.upgradeInsecureRequests=i.upgradeInsecureRequests??"always"}reset(){this.currentUrl&&URL.revokeObjectURL(this.currentUrl),this.currentUrl=void 0,this.currentResource?.close(),this.currentResource=void 0,this.pendingBuild=void 0}async build(e=!1){if(this.currentUrl)return this.currentUrl;if(this.pendingBuild)return this.pendingBuild;const t=this.doBuild(e).finally(()=>{this.pendingBuild===t&&(this.pendingBuild=void 0)});return this.pendingBuild=t,t}async doBuild(e){this.currentResource=this.pub.get(this.item);const t=await this.currentResource.link();if(!this.currentResource)return"about:blank";if(t.mediaType.isHTML){const r=await this.buildHtmlFrame(e);return this.currentUrl=r,r}else if(t.mediaType.isBitmap||t.mediaType.equals(u.SVG)){const r=await this.buildImageFrame();return this.currentUrl=r,r}else throw Error("Unsupported frame mediatype "+t.mediaType.string)}async buildHtmlFrame(e=!1){if(!this.currentResource)throw new Error("No resource loaded");const t=await this.currentResource.link(),r=await this.currentResource.readAsXML();if(!r)throw new Error(`Failed reading item ${t.href}`);const i=r.querySelector("parsererror");if(i){const s=i.querySelector("div");throw new Error(`Failed parsing item ${t.href}: ${s?.textContent||i.textContent}`)}return this.injector&&await this.injector.injectForDocument(r,t),this.finalizeDOM(r,this.pub.baseURL,t.toURL(this.baseURL)||"",t.mediaType,e,this.cssProperties,this.upgradeInsecureRequests)}async buildImageFrame(){if(!this.currentResource)throw new Error("No resource loaded");const e=await this.currentResource.link(),t=e.toURL(this.baseURL)||"",r=document.implementation.createHTMLDocument(e.title||e.href);if((e?.height||0)>0&&(e?.width||0)>0){const a=r.createElement("meta");a.name="viewport",a.content=`width=${e.width}, height=${e.height}`,a.dataset.readium="true",r.head.appendChild(a)}const i=document.createElement("img");i.src=t||"",i.alt=e.title||"",await i.decode(),r.body.appendChild(i),this.injector&&await this.injector.injectForDocument(r,new f({href:"readium-image-frame.xhtml",type:u.XHTML.string}));const s=r.createElement("style");return s.dataset.readium="true",s.textContent=`
|
|
2
|
+
html, body { width: 100%; height: 100%; margin: 0; padding: 0; font-size: 0; }
|
|
3
|
+
img { margin: 0; padding: 0; border: 0; }`,r.head.appendChild(s),this.finalizeDOM(r,this.pub.baseURL,t,e.mediaType,!0,void 0,this.upgradeInsecureRequests)}setProperties(e,t){for(const r in e){const i=e[r];i&&t.documentElement.style.setProperty(r,i)}}finalizeDOM(e,t,r,i,s=!1,a,p="always"){if(!e)return"";const b=(this.injector?.getAllowedDomains?.()||[]).map(m),d=t?R(t):void 0,g=[...new Set([...d?[d]:[],...b])].filter(Boolean);if(a&&!s&&this.setProperties(a,e),e.body.querySelectorAll("img").forEach(n=>{n.setAttribute("fetchpriority","high"),n.setAttribute("referrerpolicy","origin")}),i.isHTML&&this.pub.metadata.languages?.[0]){const n=this.pub.metadata.languages[0];if(i===u.XHTML){const h=e.documentElement.lang||e.documentElement.getAttribute("xml:lang"),c=e.body.lang||e.body.getAttribute("xml:lang");c&&!h?(e.documentElement.lang=c,e.documentElement.setAttribute("xml:lang",c),e.body.removeAttribute("xml:lang"),e.body.removeAttribute("lang")):h||(e.documentElement.lang=n,e.documentElement.setAttribute("xml:lang",n))}else i===u.HTML&&!e.documentElement.lang&&(e.documentElement.lang=n)}if(w(this.pub.metadata)==="rtl"&&!e.documentElement.dir&&!e.body.dir&&(e.documentElement.dir=y.rtl),r!==void 0){const n=e.createElement("base");n.href=r,n.dataset.readium="true",e.head.firstChild.before(n)}const l=e.createElement("meta");return l.httpEquiv="Content-Security-Policy",l.content=L(g,p,t),l.dataset.readium="true",e.head.firstChild.before(l),URL.createObjectURL(new Blob([new XMLSerializer().serializeToString(e)],{type:i.isHTML?i.string:"application/xhtml+xml"}))}}export{v as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mid as n,COMMS_VERSION as
|
|
1
|
+
import{mid as n,COMMS_VERSION as d}from"@readium/navigator-html-injectables";const a=1e4,l=5e3;class v{constructor(e,i){this.registry=new Map,this._ready=!1,this.listenerBuffer=[],this.visibleTime=0,this.visibleSince=document.hidden?void 0:performance.now(),this.visibilityHandler=this.handleVisibility.bind(this),this.handler=this.handle.bind(this),this.wnd=e,this.origin=i;try{this.channelId=window.crypto.randomUUID()}catch{this.channelId=n()}this.startGc(),window.addEventListener("message",this.handler),this.send("_ping",void 0)}set listener(e){this.listenerBuffer.length>0&&this.listenerBuffer.forEach(i=>e(i[0],i[1])),this.listenerBuffer=[],this._listener=e}clearListener(){typeof this._listener=="function"&&(this._listener=void 0)}startGc(){this.gc===void 0&&(this.handleVisibility(),document.addEventListener("visibilitychange",this.visibilityHandler),this.gc=setInterval(()=>{const e=this.visibleNow();this.registry.forEach((i,t)=>{e-i.time>a&&(console.warn(t,"event for",i.key,"was never handled!"),this.registry.delete(t))})},l))}stopGc(){this.visibleTime=this.visibleNow(),this.visibleSince=void 0,document.removeEventListener("visibilitychange",this.visibilityHandler),clearInterval(this.gc),this.gc=void 0}visibleNow(){return this.visibleTime+(this.visibleSince===void 0?0:performance.now()-this.visibleSince)}handleVisibility(){document.hidden?(this.visibleTime=this.visibleNow(),this.visibleSince=void 0):this.visibleSince===void 0&&(this.visibleSince=performance.now())}halt(){this._ready=!1,window.removeEventListener("message",this.handler),this.stopGc(),this._listener=void 0,this.registry.clear()}resume(){window.addEventListener("message",this.handler),this.startGc(),this._ready=!0}handle(e){const i=e.data;if(!i._readium){console.warn("Ignoring",i);return}if(i._channel===this.channelId)switch(i.key){case"_ack":{if(!i.id)return;const t=this.registry.get(i.id);if(!t)return;this.registry.delete(i.id),t.cb(!!i.data);return}case"_pong":this._ready=!0;default:{if(!this.ready)return;typeof this._listener=="function"?this._listener(i.key,i.data):this.listenerBuffer.push([i.key,i.data])}}}get ready(){return this._ready}send(e,i,t,r=!1,h=[]){const s=n();return t&&this.registry.set(s,{cb:t,time:this.visibleNow(),key:e}),this.wnd.postMessage({_readium:d,_channel:this.channelId,id:s,data:i,key:e,strict:r},"/",h),s}}export{v as FrameComms};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Loader as o}from"@readium/navigator-html-injectables";import{FrameComms as n}from"./FrameComms.js";import{sML as h}from"@readium/helpers";import{KeyboardConditionBridge as a}from"../../peripherals/KeyboardConditionBridge.js";class
|
|
1
|
+
import{Loader as o}from"@readium/navigator-html-injectables";import{FrameComms as n}from"./FrameComms.js";import{sML as h}from"@readium/helpers";import{KeyboardConditionBridge as a}from"../../peripherals/KeyboardConditionBridge.js";import{createSerializer as c}from"../../helpers/serialize.js";class u{constructor(t,i={},s=[],e=[],r=[]){this.timelineFragmentIds=e,this.hidden=!0,this.destroyed=!1,this.pendingUnwatchSelectors=[],this.currModules=[],this.serialize=c(),this.frame=document.createElement("iframe"),this.frame.sandbox.value="allow-same-origin allow-scripts",this.frame.classList.add("readium-navigator-iframe"),this.frame.style.visibility="hidden",this.frame.ariaHidden="true",this.frame.style.opacity="0",this.frame.style.position="absolute",this.frame.style.pointerEvents="none",this.frame.style.transition="visibility 0s, opacity 0.1s linear",this.source=t,this.contentProtectionConfig={...i},this.keyboardPeripheralsConfig=[...s],this.resizeWatchSelectors=[...r]}async load(t){return this.serialize(()=>new Promise((i,s)=>{if(this.loader){const e=this.frame.contentWindow;if([...this.currModules].sort().join("|")===[...t].sort().join("|")){try{i(e)}catch{}return}this.comms?.halt(),this.loader.destroy(),this.loader=new o(e,t),this.currModules=t,this.comms=void 0;try{i(e)}catch{}return}this.frame.onload=()=>{const e=this.frame.contentWindow;this.loader=new o(e,t),this.currModules=t;try{i(e)}catch{}},this.frame.onerror=e=>{try{s(e)}catch{}},this.frame.contentWindow.location.replace(this.source)}))}applyContentProtection(){this.comms||this.comms.resume(),this.comms.send("peripherals_protection",this.contentProtectionConfig),this.keyboardPeripheralsConfig&&this.keyboardPeripheralsConfig.length>0&&(this.conditionBridge?.destroy(),this.conditionBridge=new a(this.keyboardPeripheralsConfig,t=>{t.length>0&&this.comms.send("keyboard_peripherals",t)}),this.conditionBridge.setup()),this.contentProtectionConfig.monitorScrollingExperimental&&this.comms.send("scroll_protection",{}),this.contentProtectionConfig.protectPrinting?.disable&&this.comms.send("print_protection",this.contentProtectionConfig.protectPrinting),this.resizeWatchSelectors.forEach(t=>{this.comms.send("decoration_resize",{action:"watch",selector:t})}),this.pendingUnwatchSelectors.forEach(t=>{this.comms.send("decoration_resize",{action:"unwatch",selector:t})}),this.pendingUnwatchSelectors=[]}addResizeTarget(t){this.resizeWatchSelectors.includes(t)||this.resizeWatchSelectors.push(t),this.pendingUnwatchSelectors=this.pendingUnwatchSelectors.filter(i=>i!==t),this.comms?.ready&&this.comms.send("decoration_resize",{action:"watch",selector:t})}removeResizeTarget(t){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==t),this.comms?.ready?this.comms.send("decoration_resize",{action:"unwatch",selector:t}):this.pendingUnwatchSelectors.includes(t)||this.pendingUnwatchSelectors.push(t)}async destroy(){return this.serialize(async()=>{this.conditionBridge?.destroy(),await this.hideNow(),this.loader?.destroy(),this.frame.remove(),this.destroyed=!0})}async hide(){return this.serialize(()=>this.hideNow())}async hideNow(){if(!this.destroyed){if(this.frame.style.visibility="hidden",this.frame.ariaHidden="true",this.frame.style.opacity="0",this.frame.style.pointerEvents="none",this.hidden=!0,this.frame.blur(),this.frame.parentElement)return this.comms===void 0||!this.comms.ready?void 0:new Promise((t,i)=>{this.comms?.send("unfocus",void 0,s=>{this.comms?.halt(),t()})});this.comms?.halt()}}async show(t){return this.serialize(()=>this.showNow(t))}async showNow(t){if(this.destroyed)throw Error("Trying to show frame when it doesn't exist");if(!this.frame.parentElement)throw Error("Trying to show frame that is not attached to the DOM");return this.comms?this.comms.resume():this.comms=new n(this.frame.contentWindow,this.source),new Promise((i,s)=>{this.comms?.send("activate",void 0,()=>{this.comms?.send("focus",void 0,()=>{this.applyContentProtection(),this.timelineFragmentIds.length>0&&this.comms?.send("timeline_entries",this.timelineFragmentIds);const e=()=>{this.frame.style.removeProperty("visibility"),this.frame.style.removeProperty("opacity"),this.frame.style.removeProperty("pointer-events"),this.frame.ariaHidden=null,this.hidden=!1,h.UA.WebKit&&this.comms?.send("force_webkit_recalc",void 0),i()};t!==void 0?this.comms?.send("go_progression",t,e):e()})})})}setCSSProperties(t){this.destroyed||!this.frame.contentWindow||(this.hidden&&!this.comms&&(this.comms=new n(this.frame.contentWindow,this.source),this.comms.halt()),this.comms?.send("update_properties",t))}get iframe(){if(this.destroyed)throw Error("Trying to use frame when it doesn't exist");return this.frame}get realSize(){if(this.destroyed)throw Error("Trying to use frame client rect when it doesn't exist");return this.frame.getBoundingClientRect()}get isDestroyed(){return this.destroyed}get window(){if(this.destroyed||!this.frame.contentWindow)throw Error("Trying to use frame window when it doesn't exist");return this.frame.contentWindow}get atLeft(){return this.window.scrollX<5}get atRight(){return this.window.scrollX>this.window.document.scrollingElement.scrollWidth-this.window.innerWidth-5}get msg(){return this.comms}get ldr(){return this.loader}}export{u as FrameManager};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import P from"./FrameBlobBuilder.js";import{FrameManager as U}from"./FrameManager.js";const w=10,y=5;class F{constructor(e,i,s,c,h,r,n,p=[],o){this.pool=new Map,this.blobs=new Map,this.inprogress=new Map,this.pendingUpdates=new Map,this.injector=null,this.updateSequence=0,this.container=e,this.positions=i,this.currentCssProperties=s,this.injector=c??null,this.contentProtectionConfig=h||{},this.keyboardPeripheralsConfig=r||[],this.getFragmentIds=n??(()=>[]),this.resizeWatchSelectors=[...p],this.upgradeInsecureRequests=o??"always"}addResizeTarget(e){this.resizeWatchSelectors.includes(e)||this.resizeWatchSelectors.push(e),this.pool.forEach(i=>i.addResizeTarget(e))}removeResizeTarget(e){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==e),this.pool.forEach(i=>i.removeResizeTarget(e))}async destroy(){let e=this.inprogress.values(),i=e.next();const s=[];for(;i.value;)s.push(i.value),i=e.next();s.length>0&&await Promise.allSettled(s),this.inprogress.clear();let c=this.pool.values(),h=c.next();for(;h.value;)await h.value.destroy(),h=c.next();this.pool.clear(),this.blobs.forEach(r=>r.reset()),this.blobs.clear(),this.injector?.dispose(),this.container.childNodes.forEach(r=>{(r.nodeType===Node.ELEMENT_NODE||r.nodeType===Node.TEXT_NODE)&&r.remove()})}async update(e,i,s,c=!1){for(;this.forcedUpdate;)await this.forcedUpdate;const h=++this.updateSequence;let r=this.positions.findIndex(o=>o.locations.position===i.locations.position);if(r<0)throw Error(`Locator not found in position list: ${i.locations.position} > ${this.positions.reduce((o,g)=>g.locations.position||0>o?g.locations.position||0:o,0)}`);const n=this.positions[r].href;this.inprogress.has(n)&&await this.inprogress.get(n);const p=new Promise(async(o,g)=>{const m=[],d=[];this.positions.forEach((t,a)=>{(a>r+w||a<r-w)&&(m.includes(t.href)||m.push(t.href)),a<r+y&&a>r-y&&(d.includes(t.href)||d.push(t.href))}),m.forEach(async t=>{d.includes(t)||this.pool.has(t)&&(await this.pool.get(t)?.destroy(),this.pool.delete(t),this.pendingUpdates.has(t)&&this.pendingUpdates.set(t,{inPool:!1}))}),this.currentBaseURL!==void 0&&e.baseURL!==this.currentBaseURL&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear()),this.currentBaseURL=e.baseURL,c&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear(),this.pendingUpdates.clear());const b=async t=>{if(this.pendingUpdates.has(t)&&this.pendingUpdates.get(t)?.inPool===!1){const f=this.blobs.get(t);f&&(f.reset(),this.blobs.delete(t),this.pendingUpdates.delete(t))}if(this.pool.has(t)){const f=this.pool.get(t);if(!this.blobs.has(t))await f.destroy(),this.pool.delete(t),this.pendingUpdates.delete(t);else{await f.load(s);return}}const a=e.readingOrder.findWithHref(t);if(!a)return;this.blobs.has(t)||this.blobs.set(t,new P(e,this.currentBaseURL||"",a,{cssProperties:this.currentCssProperties,injector:this.injector,upgradeInsecureRequests:this.upgradeInsecureRequests}));const l=new U(await this.blobs.get(t).build(),this.contentProtectionConfig,this.keyboardPeripheralsConfig,this.getFragmentIds(t),this.resizeWatchSelectors);return t!==n&&await l.hide(),this.container.appendChild(l.iframe),await l.load(s),this.pool.set(t,l),l};try{await Promise.all(d.filter(t=>t===n).map(t=>b(t)))}catch(t){g(t);return}if(h!==this.updateSequence){o();return}Promise.all(d.filter(t=>t!==n&&!this.inprogress.has(t)).map(async t=>{const a=b(t);this.inprogress.set(t,a);try{await a}finally{this.inprogress.get(t)===a&&this.inprogress.delete(t)}})).catch(t=>console.warn("Failed preloading frame",t));const u=this.pool.get(n);if(!u){o();return}if(u?.source!==this._currentFrame?.source||c){if(await this._currentFrame?.hide(),h!==this.updateSequence){o();return}const t=this.pool.get(n);if(!t){o();return}if(await t.load(s),h!==this.updateSequence){o();return}const a=this.pool.get(n);if(!a){o();return}if(await a.show(i.locations.progression),this._currentFrame=a,u){const l=this.container.ownerDocument.activeElement;l&&l.tagName==="IFRAME"&&l!==u.iframe&&u.iframe.focus({preventScroll:!0})}}o()});if(this.inprogress.set(n,p),c){const o=p.catch(()=>{});this.forcedUpdate=o,o.then(()=>{this.forcedUpdate===o&&(this.forcedUpdate=void 0)})}try{await p}finally{this.inprogress.delete(n)}}setCSSProperties(e){if(!((s,c)=>{const h=Object.keys(s),r=Object.keys(c);if(h.length!==r.length)return!1;for(const n of h)if(s[n]!==c[n])return!1;return!0})(this.currentCssProperties||{},e)){this.currentCssProperties=e,this.pool.forEach(s=>{s.setCSSProperties(e)});for(const s of this.blobs.keys())this.pendingUpdates.set(s,{inPool:this.pool.has(s)})}}get currentFrames(){return[this._currentFrame]}get currentBounds(){const e={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentFrames.forEach(i=>{if(!i)return;const s=i.realSize;e.x=Math.min(e.x,s.x),e.y=Math.min(e.y,s.y),e.width+=s.width,e.height=Math.max(e.height,s.height),e.top=Math.min(e.top,s.top),e.right=Math.min(e.right,s.right),e.bottom=Math.min(e.bottom,s.bottom),e.left=Math.min(e.left,s.left)}),e}}export{F as FramePoolManager};
|