1+ import frontend , { PageState } from '@/store/frontend'
2+
3+ const PAGE_STATE_MULTIPLIERS : Record < PageState , number > = { focused : 1 , blurred : 5 , hidden : 10 }
4+
5+ const pageResumeListeners = new Set < ( ) => void > ( )
6+ if ( typeof document !== 'undefined' ) {
7+ const notify = ( ) => pageResumeListeners . forEach ( ( fn ) => fn ( ) )
8+ document . addEventListener ( 'visibilitychange' , ( ) => { if ( ! document . hidden ) notify ( ) } )
9+ window . addEventListener ( 'focus' , notify )
10+ }
11+
112/**
213 * Represents a function that can be OneMoreTime valid action
314 */
@@ -39,6 +50,8 @@ export interface OneMoreTimeOptions {
3950 * OneMoreTime instance.
4051 */
4152 disposeWith ?: unknown
53+
54+ disablePageThrottle ?: boolean
4255}
4356
4457/**
@@ -55,6 +68,12 @@ export class OneMoreTime {
5568
5669 private timeoutId ?: ReturnType < typeof setTimeout >
5770
71+ private onPageResume = ( ) => {
72+ if ( this . isDisposed || this . isPaused || this . isRunning || ! this . timeoutId ) return
73+ this . killTask ( )
74+ this . start ( )
75+ }
76+
5877 /**
5978 * Constructs an instance of OneMoreTime, optionally starting the action immediately.
6079 * @param {OneMoreTimeOptions } options Configuration options for the instance.
@@ -65,10 +84,17 @@ export class OneMoreTime {
6584 private action ?: OneMoreTimeAction ,
6685 ) {
6786 this . watchDisposeWith ( )
87+ if ( ! this . options . disablePageThrottle ) pageResumeListeners . add ( this . onPageResume )
6888 // One more time
6989 this . softStart ( )
7090 }
7191
92+ private getEffectiveDelay ( baseDelay ?: number ) : number | undefined {
93+ if ( baseDelay === undefined ) return undefined
94+ if ( this . options . disablePageThrottle ) return baseDelay
95+ return baseDelay * PAGE_STATE_MULTIPLIERS [ frontend . page_state ]
96+ }
97+
7298 private killTask ( ) : void {
7399 if ( this . timeoutId ) {
74100 clearTimeout ( this . timeoutId )
@@ -85,6 +111,7 @@ export class OneMoreTime {
85111 // eslint-disable-next-line
86112 if ( ! ref . deref ( ) || ref . deref ( ) . _isDestroyed ) {
87113 this . isDisposed = true
114+ pageResumeListeners . delete ( this . onPageResume )
88115 this . killTask ( )
89116 clearInterval ( id )
90117 }
@@ -95,6 +122,7 @@ export class OneMoreTime {
95122 // Celebrate and dance so free
96123 [ Symbol . dispose ] ( ) : void {
97124 this . isDisposed = true
125+ pageResumeListeners . delete ( this . onPageResume )
98126 this . killTask ( )
99127 }
100128
@@ -150,13 +178,13 @@ export class OneMoreTime {
150178 this . options . onError ?.( error )
151179 // Oh yeah, alright, don't stop the dancing
152180 // eslint-disable-next-line no-promise-executor-return
153- await new Promise ( ( resolve ) => setTimeout ( resolve , this . options . errorDelay ) )
181+ await new Promise ( ( resolve ) => setTimeout ( resolve , this . getEffectiveDelay ( this . options . errorDelay ) ) )
154182 } finally {
155183 this . isRunning = false
156184 }
157185
158186 if ( ! this . isPaused && ! this . isDisposed ) {
159- this . timeoutId = setTimeout ( ( ) => this . start ( ) , this . options . delay )
187+ this . timeoutId = setTimeout ( ( ) => this . start ( ) , this . getEffectiveDelay ( this . options . delay ) )
160188 }
161189 }
162190
0 commit comments