11'use strict' ;
22
33import React , { Component , PropsWithChildren } from 'react' ;
4- import { View , ViewStyle } from 'react-native' ;
4+ import {
5+ AppState ,
6+ AppStateStatus ,
7+ NativeEventSubscription ,
8+ View ,
9+ ViewStyle ,
10+ } from 'react-native' ;
511
612const DEFAULT_DELAY = 1000 ;
713
@@ -10,6 +16,7 @@ export type Props = {
1016 style ?: ViewStyle ;
1117 onChange ?: ( isVisible : boolean ) => void ;
1218 delay ?: number ;
19+ propKey ?: any ;
1320} ;
1421
1522class TimeoutHandler {
@@ -60,71 +67,109 @@ export default class ViewPortDetector extends Component<
6067 private lastValue : boolean | null = null ;
6168 private interval : TimeoutHandler | null = null ;
6269 private view : View | null = null ;
70+ private lastAppStateActive = false ;
71+ private appStateSubscription : NativeEventSubscription | null = null ;
6372
6473 constructor ( props : Props ) {
6574 super ( props ) ;
6675 this . state = { rectTop : 0 , rectBottom : 0 } ;
6776 }
6877
6978 componentDidMount ( ) {
79+ this . lastAppStateActive = AppState . currentState === 'active' ;
80+ this . appStateSubscription = AppState . addEventListener (
81+ 'change' ,
82+ this . handleAppStateChange
83+ ) ;
7084 if ( this . hasValidTimeout ( this . props . disabled , this . props . delay ) ) {
7185 this . startWatching ( ) ;
7286 }
7387 }
7488
7589 componentWillUnmount ( ) {
90+ this . appStateSubscription ?. remove ( ) ;
91+ this . appStateSubscription = null ;
7692 this . stopWatching ( ) ;
7793 }
7894
79- hasValidTimeout ( disabled ?: boolean , delay ?: number ) : boolean {
95+ hasValidTimeout = ( disabled ?: boolean , delay ?: number ) : boolean => {
8096 let disabledValue = disabled ?? false ;
8197 let delayValue = delay ?? DEFAULT_DELAY ;
82- return ! disabledValue && delayValue > 0 ;
83- }
98+ return (
99+ AppState . currentState === 'active' && ! disabledValue && delayValue > 0
100+ ) ;
101+ } ;
84102
85103 UNSAFE_componentWillReceiveProps ( nextProps : Props ) {
86104 if ( ! this . hasValidTimeout ( nextProps . disabled , nextProps . delay ) ) {
87105 this . stopWatching ( ) ;
88106 } else {
89- this . lastValue = null ;
107+ if ( this . props . propKey !== nextProps . propKey ) {
108+ this . lastValue = null ;
109+ }
90110 this . startWatching ( ) ;
91111 }
92112 }
113+ handleAppStateChange = ( nextAppState : AppStateStatus ) => {
114+ let nextAppStateActive = nextAppState === 'active' ;
115+ if ( this . lastAppStateActive !== nextAppStateActive ) {
116+ this . checkVisibility ( ) ;
117+ }
118+ this . lastAppStateActive = nextAppStateActive ;
119+
120+ if ( ! this . hasValidTimeout ( this . props . disabled , this . props . delay ) ) {
121+ this . stopWatching ( ) ;
122+ } else {
123+ this . startWatching ( ) ;
124+ }
125+ } ;
93126
94- private startWatching ( ) {
127+ startWatching = ( ) => {
95128 if ( this . interval ) {
96129 return ;
97130 }
98- this . interval = setIntervalWithTimeout ( ( ) => {
99- if ( ! this . view ) {
100- return ;
101- }
102- this . view . measure ( ( _x , _y , width , height , _pageX , _pageY ) => {
103- this . checkInViewPort ( width , height ) ;
104- } ) ;
105- } , this . props . delay || DEFAULT_DELAY ) ;
106- }
131+ this . interval = setIntervalWithTimeout (
132+ this . checkVisibility ,
133+ this . props . delay || DEFAULT_DELAY
134+ ) ;
135+ } ;
107136
108- private stopWatching ( ) {
137+ stopWatching = ( ) => {
109138 this . interval ?. clear ( ) ;
110139 this . interval = null ;
111- }
140+ } ;
112141
113- private checkInViewPort ( width ?: number , height ?: number ) {
142+ checkVisibility = ( ) => {
143+ if ( ! this . view ) {
144+ return ;
145+ }
146+
147+ if ( AppState . currentState !== 'active' ) {
148+ this . updateVisibility ( false ) ;
149+ return ;
150+ }
151+
152+ this . view . measure ( ( _x , _y , width , height , _pageX , _pageY ) => {
153+ this . checkInViewPort ( width , height ) ;
154+ } ) ;
155+ } ;
156+ checkInViewPort = ( width ?: number , height ?: number ) => {
114157 let isVisible : boolean ;
115158 // Not visible if any of these are missing.
116159 if ( ! width || ! height ) {
117160 isVisible = false ;
118161 } else {
119162 isVisible = true ;
120163 }
164+ this . updateVisibility ( isVisible ) ;
165+ } ;
121166
167+ updateVisibility = ( isVisible : boolean ) => {
122168 if ( this . lastValue !== isVisible ) {
123169 this . lastValue = isVisible ;
124170 this . props . onChange ?.( isVisible ) ;
125171 }
126- }
127-
172+ } ;
128173 render ( ) {
129174 return (
130175 < View
0 commit comments