Giter VIP home page Giter VIP logo

react-native-user-inactivity's Introduction

react-native-user-inactivity

Version Documentation Maintenance License: MIT

Functional React Native component that notifies when the user stops interacting with the mobile screen for a given amount of time.

As of version 1.1.0, react-native-user-inactivity resets the timer also when the keyboard appears or disappears. If you want to avoid this behaviour, you can set the skipKeyboard property to true.

As of version 1.0.0, react-native-user-inactivity has been rebuilt as a functional component that uses the new React Hook API. Thanks to usetimeout-react-hook, react-native-user-inactivity supports timers different than the standard one (setTimeout). This has solved some of the most recurrent issues, such as #12, #16, #17.

Install

npm install react-native-user-inactivity

If you are running a version of react < 17 you'll need to include the --legacy-peer-deps flag.

npm install react-native-user-inactivity --legacy-peer-deps

๐Ÿ”‘ Key features

  • ๐Ÿฅ‡ supports generic timers (you're no longer constrained to setTimeout)
  • โš ๏ธ optional reset capability of the timer
  • โœจ super elastic behaviour thanks to the Hooks API
  • ๐Ÿ’ช written in TypeScript
  • โœ”๏ธ the core logic of this component is delegated to usetimeout-react-hook, which has 100% code coverage

โ” How to use

This package primarily exposes a single functional component, UserInactivity. The signature of the UserInactivity React props is the following:

interface UserInactivityProps<T = unknown> {
  /**
   * Number of milliseconds after which the view is considered inactive.
   * If it changed, the timer restarts and the view is considered active until
   * the new timer expires.
   * It defaults to 1000.
   */
  timeForInactivity?: number;

  /**
   * If it's explicitly set to `true` after the component has already been initialized,
   * the timer restarts and the view is considered active until the new timer expires.
   * It defaults to true.
   */
  isActive?: boolean;

  /**
   * Generic usetimeout-react-hook's TimeoutHandler implementation.
   * It defaults to the standard setTimeout/clearTimeout implementation.
   * See https://github.com/jkomyno/usetimeout-react-hook/#-how-to-use.
   */
  timeoutHandler?: TimeoutHandler<T>;

  /**
   * Children components to embed inside UserInactivity's View.
   * If any children component is pressed, `onAction` is called after
   * `timeForInactivity` milliseconds.
   */
  children: React.ReactNode;

  /**
   * If set to true, the timer is not reset when the keyboard appears
   * or disappears.
   */
  skipKeyboard?: boolean;

  /**
   * Optional custom style for UserInactivity's View.
   * It defaults to { flex: 1 }.
   */
  style?: StyleProp<ViewStyle>;

  /**
   * Callback triggered anytime UserInactivity's View isn't touched for more than
   * `timeForInactivity` seconds.
   * It's `active` argument is true if and only if the View wasn't touched for more
   * than `timeForInactivity` milliseconds.
   */
  onAction: (active: boolean) => void;
}

When a native timer is needed (in order to avoid issues such as #12, #16, #17) an implementation of usetimeout-react-hook's TimeoutHandler should be passed to the timeoutHandler prop. A default one (BackgroundTimer) is optionally provided: in order to use it you must:

  • manually run: npm i -S react-native-background-timer
  • manually link the native library: react-native link react-native-background-timer

In case of doubts, please refer to the official react-native-background-timer repository.

The default BackgroundTimer can be used like this:

import UserInactivity from 'react-native-user-inactivity';
import BackgroundTimer from 'react-native-user-inactivity/lib/BackgroundTimer';

export default () => {
  return (
    <UserInactivity
      timeForInactivity={2000}
      timeoutHandler={BackgroundTimer}
      onAction={isActive => { console.log(isActive); }}
      style={{ flex: 1, paddingTop: '10%' }}
    >
  );
}

Warning: it seems that react-native-background-timer doesn't work properly with Android 10+ (#41). I'm currently unable to reproduce the problem, but help from the open-source community on this matter is certainly appreciated.

โœจ Typings

Since the component itself is written in TypeScript, your editor's intellisense system should automagically detect the typings file (even if you're using plain JS!), thus providing a better developer experience. In fact, autocomplete capabilities and warning should come for free as you're typing the props to pass to the UserInactivity component.

๐Ÿ’ช Practical Example

import React, { useState } from 'react';
import { View, Text, TextInput, Button } from 'react-native';
import UserInactivity from 'react-native-user-inactivity';

export default () => {
  const [active, setActive] = useState(true);
  const [timer, setTimer] = useState(2000);

  return (
    <View style={{ flex: 1 }}>
      <UserInactivity
        isActive={active}
        timeForInactivity={timer}
        onAction={isActive => { setActive(isActive); }}
        style={{ flex: 1, paddingTop: '10%' }}
      >
        <Button id="btn-1" title="1 Press this to simulate activity" />
        <Button id="btn-2" title="2 Press this to simulate activity" />
        <Text id="text-1" style={{ textAlign: 'center' }}>Type below to simulate activity</Text>
        <TextInput
          id="text-input-1"
          style={{height: 40, borderColor: 'gray', borderWidth: 1}}
          onChange={() => { setActive(true); }}
          textContentType="creditCardNumber"
          value={timer.toString(10)}
          onChangeText={text => setTimer(Number.parseInt(text || 0, 10))}
        />
      </UserInactivity>
      <View style={{ flex: 3, backgroundColor: '#fcfcaa', }}>
        <Text style={{ textAlign: 'center' }}>{active ? 'ACTIVE' : 'NOT ACTIVE'}</Text>
        <Button title="Manually set to Active" onPress={() => { setActive(true); }} />
      </View>
    </View>
  );
}

Also, please checkout the example on Snack/Expo.


๐Ÿš€ Build package

This package is built using TypeScript, so the source needs to be converted in JavaScript before being usable by the users. This can be achieved using TypeScript directly:

npm run build

๐Ÿ‘ค Author

Alberto Schiabel

๐Ÿค Contributing

Contributions, issues and feature requests are welcome!
Feel free to check issues page. The code is short, throughly commented and well tested, so you should feel quite comfortable working on it. If you have any doubt or suggestion, please open an issue.

โš ๏ธ Issues

Chances are the problem you have bumped into have already been discussed and solved in the past. Please take a look at the issues (both the closed ones and the comments to the open ones) before opening a new issue. Unfortunately, at the moment I'm not able to offer fast support, because I am a student worker and React Native is no longer part of my main tech stack.

๐Ÿฆ„ Show your support

Give a โญ๏ธ if this project helped or inspired you! In the future, I might consider offering premium support to Github Sponsors.

๐Ÿ“ License

Built with โค๏ธ by Alberto Schiabel.
This project is MIT licensed.

Related packages

react-native-user-inactivity's People

Contributors

jamesblewis avatar jkomyno avatar tchernyavskydaniil avatar wilq32-pwitkowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-user-inactivity's Issues

Doesn't Work On Pause

So I tested this package out on an iOS simulator and console logged for an timeForInactivity of 10 sec. It works when the app is in the foreground but does nothing in the background. Is this intentional?

How to stop timer while navigating on next Screen?

Hi,

I am using UserInactivity component on the screen and timer does not stop while navigating on other screens, it works on other screens too. Can you guide me how to stop UserInactivity component on other screens?

how to reset the interval time?

The issue is that if UserInactivity is triggered with a 10min time interval and if we want to change the interval in middle to 1min then what happens is first it will work for 10 min as it was triggered first and once the process is completed then only it will work for 1 min so, is there any way through which we can reset the time interval.

ERESOLVE unable to resolve dependency tree

PS C:\Anywhere> npm install react-native-user-inactivity                   
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: [email protected]
npm ERR! node_modules/react-native
npm ERR!   react-native@"0.64.3" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react-native@"^0.63.0" from [email protected]
npm ERR! node_modules/react-native-user-inactivity
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!

... Omit lines

Error: Attempted to remove more RTCKeyboardObserver Listeners than needed

Context:
React native 0.62.2
iOS 13

How i implemented:

const logout = () => {
props.navigation.navigate('Splash')
}

<UserInactivity
isActive={active}
timeForInactivity={timer}
onAction={isActive => { isActive ? console.log("I'm active") : logout() }}>

// App components

I am attempting to use this library to detect for user inactivity and if the user is inactive, I would like to log the user out of the app. When the logout() method is called and the page is routed to splash, I get the following error: Attempted to remove more RTCKeyboardObserver Listeners than needed. May I know if this is a problem due to the library?

Screenshot 2020-06-12 at 3 06 36 PM

Not working when App is in Background or Phone locked (Android)

Hi there,

I have been noticing some really strange behavior with this Inactivity package and I wonder if anyone have had the some problem before.

So, when I run the app in debug mode, everything runs smoothly and as it should, but when I deploy the app I start to get weird issues with the Timer. I think it is not triggering the Inactivity, but I am not sure.

Replication steps:

  • login
  • put the app in the background or simply lock the phone.
  • leave it for 10+ minutes which is my time for Inactivity (600.000ms)
  • open the app again
  • the inactivity alert does not show up, even if scroll the screen up and down
  • when I change screens, the inactivity alert shows up and tries to log me out (which fails because y this time my login token is invalid)

I think there something wrong with the timer when it is NOT running in Debugger mode, as when I run the app in debug mode all works as it should.

Here's how I use my component:

<Inactivity name='NameOfPageView' navigation={this.props.navigation}>
         //Other components go here   
</Inactivity>

Here's my Inactivity component:

import React from 'react';
import { View, Alert, YellowBox } from 'react-native'
import Analytics from './Analytics'
import LogoutService from '../Logout/LogoutService';
import { connect } from 'react-redux';
import { globalBegin, globalUserNotLoggedIn } from '../Shared/Global/GlobalActions';
import UserInactivity from 'react-native-user-inactivity';
import Spinner from '../Components/Spinner';

YellowBox.ignoreWarnings(['Setting a timer for a long period of time']);

class Inactivity extends React.Component{

    constructor(props) {
        super(props);
        this.state = {
            name: props.name,
            timeout: 600000,
            active: true,
        }
    }

    onAction = (active) => {
        this.setState({
            active,
        });
        
        if(active) return;

        this.onInactivity(this.state.name);
    }

    onInactivity = (name) => {
        if(this.props.isLoggedin)
        {
            var analytics = Analytics.create(name, 'logout');
            var traceId = analytics.getTraceId();
            analytics.trackEvent();
            return Alert.alert( 
                '',
                global.inactivity.Message,
                [
                    {   
                        text: 'OK', 
                        onPress: () => {
                                LogoutService
                                    .setTraceId(traceId)
                                    .logout()
                                    .then(() => {
                                        this.props.userLogout();
                                    })
                                    .catch(function (error) {
                                        analytics.trackException(error.stack);
                                        this.props.userLogout();
                                    });
                        }
                    }
                ],
                {cancelable: false }
            );
        }
    }

    render() {
        return (
            <UserInactivity 
                onAction={this.onAction} 
                timeForInactivity={this.state.timeout} >
                <Spinner visible={this.props.isBusy}/>
                <View style={{ flex: 1}}>
                    {this.props.children}
                </View>
            </UserInactivity>
        );
    }

}

const mapStateToProps = reduxState => {
    return {
        isLoggedin: reduxState.global.user.isLoggedin,
        isBusy: reduxState.global.screen.isBusy,
    }
};

const mapDispatchToProps = dispatch => {
    return {
        actionBegin: () => { dispatch(globalBegin()) },
        userLogout: () => { dispatch(globalUserNotLoggedIn()) },
    };
};

module.exports = connect(mapStateToProps, mapDispatchToProps) (Inactivity);

I hadn't checked this on iOS yet.
Any idea of what can possibly be wrong? Any tips?
All help is welcome.

Thanks

Duplicate Module error

Thank you for this library. I have been using it in my react-native/expo app for several months. However, I am in the process of upgrading my app to Expo's SDK v35. I saw the v1.0.0 of this was out (I was on v0.1.3-next); so I upgraded.

When doing so, and trying to start my app expo start, I recieve an error:
Duplicate module name: react-animated from this library.

Downgrading to 0.1.3-next sorts the error; however, I always like to keep my dependencies somewhat up-to-date.

Thx in advance

How to reset timer from Component

Hi,

Thanks for the library. I use react-navigation to move between screens. while navigate to another screen I want to disable the timer and when i come back to previous screen I want to reset the timer. is there any props to handle these two options. Please let me know.

Keeps timing users out while using the app

Hi @jkomyno,

Thanks for this awesome contribution to the react native community. I seem to be having some issues with our implementation as users keep getting timed out while they are using our app, and they have to sign back in after which they are immediately timed out. Below is a sample
Of our code

`
<UserInactivity
timeForInactivity={SIGNOUT_INTERVAL}
timeoutHandler={BackgroundTimer}
isActive={store.getState().inactivityState}
onAction={isActive => this.onAction(isActive)}
>







'

Thanks for your help in advance.

node module download error

By this library i am not able to download node module by npm i , every time i have to run npm install --legacy-peer-dep which ignores all library peer dependancy.

Not working if add alert component to check inactivity at the end of the timer

@jkomyno Not working if add alert component to check inactivity at the end of the timer. I'm aware that it works only if the user touch the surface. However, there is events where we have to use the alert component.

Is it possible to provide a reference for us to use it within the alert component to mark it as active?

or could you provide the codes for initialising the reference to the type script component. Thanks.

Conflict with React

Hi, when I add the version v1.0, are created a folder named node_modules in the folder of the package with the folders .bin and react, this folder is conflicting with the project, resulting in the error:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

If I delete the folder node_modules the app and lib will work again.

Convert this package using hooks

React Native has been supporting hooks since v0.59 for functional components.
This would allow a number of benefits:

  • simpler to mantain states updates that reflect props update
  • possibility to decouple timeout-to-state management
  • easy API to support something similar to #5 (although I won't expose a static setIsActive() method, I'll simply allow an optional isActive boolean parameter)

Does handleInactivity need to be called in componentWillMount()?

In my current use case, I don't want onAction to fire when the component mounts. Could we add a prop that allows that call to be skipped? I'm guessing clearTimer and resetTimeout would have to be called instead.

Also, componentWillMount is deprecated so this should probably be moved to componentDidMount.

Not working on Android

Even though on IOS works ok, on android I get "Setting a timer for a long period of time".. warning.
And even if I make the timeForInactivity to 1 minute (which doesn't produce the error), it never triggers the onAction method with parameter false.

onAction getting called twice

Recreate:

<View>
      <UserInactivity
        isActive={active}
        timeForInactivity={5000}
        timeoutHandler={BackgroundTimer}
        onAction={(isActive) => {
          console.log(isActive);
        }}
        style={{flex: 1, paddingTop: '10%'}}>
        <Text>Foo</Text>
      </UserInactivity>
    </View>

Behavior:

console.log gets called twice every 5 seconds

I'm using this background timer:

import BackgroundTimer from 'react-native-user-inactivity/lib/BackgroundTimer';

Expected behavior:

onAction should only be called once

Timeout not reset when user typing on keyboard

In my app, there's a textinput inside UserInactivity element. And when user typing in textinput, UserInactivity doesn't reset the timeout and therefore trigger onInactivity even if the app is not technically inactive.

Haste Module naming collision

jest-haste-map: Haste module naming collision:

Duplicate module name: react-native
paths: project-name/node_modules/react-native-user-inactivity/node_modules/react-native/package.json collides with project-namel/node_modules/react-native/package.json

jest-haste-map: Haste module naming collision:
Duplicate module name: react-animated

Paths: project-name/node_modules/react-native-user-inactivity/node_modules/react-native/Libraries/Animated/release/package.json collides with project-name/node_modules/react-native/Libraries/Animated/release/package.json

This warning is caused by hasteImpl returning the same name for different files.
jest-haste-map: Haste module naming collision:
Duplicate module name: Sample

Paths: project-name/node_modules/react-native-user-inactivity/node_modules/react-native/Libraries/Sample/package.json collides with /project-name/FreshTool/node_modules/react-native/Libraries/Sample/package.json

expo demo need update, not working

Trying to run demo project from readme
https://snack.expo.io/B1sjE9uMH

got error:

App.js (1247:889)
ViewPropTypes has been removed from React Native. Migrate to ViewPropTypes exported from 'deprecated-react-native-prop-types'.
(Device)
  Evaluating module://react-native-user-inactivity.js
  Evaluating module://App.js.js
  Loading module://App.js

working only if switch to expo v.44

Support changing `onAction` prop

The timers ignore changes to onAction, therefore when it changes the timeout calls the first version of the function that was passed, and not the latest. This is what causes issues like #46 and #54. I imagine the solution might not be that straightforward, since resetting the timer every time this prop changes would be unwanted, but perhaps a good solution would be to use a ref to the onAction inside the timeout callback, and updating that ref with the value of onAction on every render. This way, a stale closure isn't called when the timeout ends.

Calling setIsActive from outside?

So I notice that in some situation (like keyboard input and modal's input etc) the setIsActive function isnt call hence the timer dont start. So I was just wondering if you can just add the reference to the component so that we can call the setIsActive function from outside the component? Something like this:
add this to index.js

static propTypes = {
   ...
   onRef: PropTypes.func,
}

static defaultProps = {
   ...
   onRef: () => {},
}

componentDidMount() {
   this.props.onRef(this);
}

componentWillUnmount() {
   ...
   this.props.onRef(undefined)
}

And when you use the package you can do this:

onRef = (ref) => {
    this.userInactivity = ref;
  }

onThingsHappen = () => {
   // do something else
   // when something finish call setIsActive to start timer:
   this.userInactivity.setIsActive();
}



<UserInactivity onRef={this.onRef} ... >
</UserInactivity>

Something like that?

Keyboard activity outside this App

Does the inactivity track within the App or even outside this App. We want to capture any Keyboard events not just within this App to determine the activity of the User. If the app runs in the background and the User use Keyboard in another App, this should consider as Activity.

In a sense, we want to gather user activity overall with his phone. Will this package works for our case?

getting incorrect values from redux inside onAction

I'm trying to logout user after sometime when there is no item in cart (stored in redux) in my kiosk type application.

const handleActivity = (isActive: boolean) => {
      setActive(isActive);
      console.log('active: ' + isActive);
      if (!isActive && cartItems.length==0) {
            logout();
      }
}

But length is returned 0 when the function is called during first inactivity when there is an item in the cart. If the same function is called on a button press, correct value is returned.
What should I do to get correct value everytime?

Unable to install the package on RN 39.0.4

Running into this error instantly when running npm install react-native-user-inactivity

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: undefined@undefined
npm ERR! Found: [email protected]
npm ERR! node_modules/react-native
npm ERR!   react-native@"https://github.com/expo/react-native/archive/sdk-39.0.4.tar.gz" from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react-native@"^0.61.3" from [email protected]
npm ERR! node_modules/react-native-user-inactivity
npm ERR!   react-native-user-inactivity@"*" from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR! See /Users/myusername/.npm/eresolve-report.txt for a full report.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/myusername/.npm/_logs/2020-11-26T02_00_43_440Z-debug.log

Improve README.md

  • Rephrase introduction
  • Suggest looking in the closed issues for solutions to any kind of problem

Using Background timer with user inactivity

I have created a component that wraps my app navigator, the problem I am experiencing is that after the onAction callback gets fired the timer seems to carry on counting and therefore, executing the callback function passed to onAction every few seconds

timeForInactivity = 15

InactivityComponent:

import React from 'react';
import UserInactivity from 'react-native-user-inactivity';
import BackgroundTimer from 'react-native-user-inactivity/lib/BackgroundTimer';

export default InActivityContainer = (props) => {
    
    return(
        <UserInactivity
            timeForInactivity={props.timeForInactivity * 60 * 1000}
            onAction={isActive => {
                props.onAction(isActive);
            }}
            style={{ flex: 1 }}
        >
            {props.children}
        </UserInactivity>
    )
}

Inactivity wrapping App Navigator inside of App.js

<InactivityContainer
          onAction={(isActive) => {
            if (!isActive) {
              store.dispatch({ type: types.LOGOUT });
              navigate("App", {});
            }
          }}
          timeForInactivity={timeForTimeout}
        >
          {Platform.OS === "ios" && <StatusBar barStyle="default" />}
          <AppNavigator
            ref={(navigator) => {
              nav = navigator;
              setNavigator(navigator);
            }}
            onNavigationStateChange={(prevState, newState) => {
              Analytics.setCurrentScreen(getCurrentRoute(newState));
            }}
          />
        </InactivityContainer>

Usage With React Navigation

Relevant app dependencies:

"react-native": "0.61.5",
"@react-navigation/bottom-tabs": "5.5.0",
"@react-navigation/drawer": "5.8.0",
"@react-navigation/material-bottom-tabs": "5.2.8",
"@react-navigation/native": "5.4.3",
"@react-navigation/stack": "5.4.0",
"react-native-background-timer": "^2.2.0",
"react-native-user-inactivity": "^1.1.0",

React Navigation v5 allows routers to be React components. I have a Main router that defines routes that are available once a user has logged in. I would like to logout the user if they have met the inactivity threshold on any of these screens. Here is the Main router:

const MainRouter: FC<MainRouterProps> = ({ deviceInfo }: MainRouterProps) => {
	const isTablet = getDeviceInfoValue(deviceInfo, 'is_tablet');

	return (
		<InactivityMonitor>
			<DrawerStack.Navigator 
				initialRouteName='Dashboard'
				drawerType='front'
				backBehavior='history'
				lazy={true}
				hideStatusBar={false}
				minSwipeDistance={200}
				drawerContent={(props) => <Drawer {...props} />}
			>
				<DrawerStack.Screen 
					name='Dashboard' 
					component={Dashboard} 
				/>
				<DrawerStack.Screen 
					name='Workroom' 
					component={WorkroomRouter} 
				/>
				<DrawerStack.Screen 
					name='Libraries' 
					component={Libraries} 
				/>
				<DrawerStack.Screen 
					name='Directory' 
					component={Directory}
				/>
				<DrawerStack.Screen 
					name='DirectorySearch' 
					component={DirectorySearch} 
				/>
				<DrawerStack.Screen 
					name='SearchResults' 
					component={SearchResults} 
				/>
				<DrawerStack.Screen 
					name='Profile' 
					component={ProfileRouter} 
				/>
				<DrawerStack.Screen 
					name='ProfileSearch' 
					component={ProfileRouter} 
				/>
				<DrawerStack.Screen 
					name='Settings' 
					component={isTablet ? SettingsTablet : SettingsRouter} 
				/>
			</DrawerStack.Navigator>
		</InactivityMonitor>
	);
}

the InactivityMonitor component wraps the UserInactivity component from the react-native-user-inactivity package and is implemented as such:

import React, { FC, ReactNode, useEffect, useState, memo } from 'react';
import { NativeModules } from 'react-native';
import UserInactivity from 'react-native-user-inactivity';
import BackgroundTimer from 'react-native-user-inactivity/lib/BackgroundTimer';
import { useNavigation } from '@react-navigation/native';
import { IAlertDialogContextItem } from '../../contexts/alertDialog/AlertDialogProvider';
import { compose, withDb, withAlertDialog } from '../../hocs';
import { getPortalAndUserIds } from '../../storage';
import { IDatabase, INativeModules } from '../../types';
import { logError, translate } from '../../util';

interface InactivityMonitorProps {
	children: ReactNode;
	db: IDatabase;
	enqueueAlertDialog: (item: IAlertDialogContextItem | any) => void;
}

const InactivityMonitor: FC<InactivityMonitorProps> = ({ children, db, enqueueAlertDialog }) => {
	const [active, setActive] = useState<boolean>(true);
	const [timer, setTimer] = useState<number>(1000 * 60 * 60 * 3); // default 3 hours
	const navigation = useNavigation();

	useEffect(() => {
		getPortalInactivityTimeout();
	}, []);

	useEffect(() => {
		if (!active) {
			onInactiveTimeout();
		}
	}, [active]);

	const getPortalInactivityTimeout = async () => {
		console.log('InactivityMonitor: mounting. Calling getPortalInactivityTimeout()');

		try {
			const { portalPk } = await getPortalAndUserIds();
			const timeoutMs = await db.read.mobileInactivityTimeout(portalPk);

			console.log('InactivityMonitor: timeoutMs:', timeoutMs);

			if (timeoutMs > 0) {
				setTimer(timeoutMs);
			}
		} catch (error) {
			logError(error, 'InactivityMonitor getPortalInactivityTimeout()');
		}
	};

	const onInactiveTimeout = () => {
		console.log('InactivityMonitor: calling onInactiveTimeout()');

          const { RNViewerMethods } = NativeModules as INativeModules;
		RNViewerMethods.closeViewerScreen();
		navigation.navigate('DeviceAuth');
		enqueueAlertDialog && enqueueAlertDialog({ message: translate('session_timeout') });
	};

	return (
		<UserInactivity
			isActive={active}
			timeForInactivity={timer}
			// @ts-ignore
			timeoutHandler={BackgroundTimer}
			onAction={(isActive) => { setActive(isActive); }}
		>
			{children}
		</UserInactivity>
	);
};

export default compose(
	memo,
	withDb,
	withAlertDialog
)(InactivityMonitor);

it looks like any screen interactions (including button presses, etc) do NOT reset the timer given this use case. I have tested with a 1 min (60000ms) expiration several times, and the onAction function is ran even if I am in the middle of touching the screen or otherwise interacting with the UI. Does the UserInactivity component only reset the timer if its immediate children are touched or interacted with on the device's screen?

Button press

I am curious how hard it would be to be able to tell onAction if a user pressed a button (touchableWithoutFeedback). I like and appreciate the default behavior of this component but am curious if it would be able to add some more context to onAction, specifically if the user has pressed a certain button and handle that differently.

My situation is that onAction, I want to dismiss a modal, but inside that modal there is a button to navigate. Currently I cannot press this button because it will hide the modal.

Do you have any suggestions?

Is User considered active while watching a video?

Hi, this isn't really an issue but more of a question. I'm just wondering if a user is watching a video, does your library start counting down the timer. I have the timeout set for 20 minutes and then would log the user out. But if they are watching a 30 minute video inside my app I don't want to log them out while they are watching the video even though they have not touched the screen. Thanks!

What number of timer can I set?

Do you have any timer limit? Because when I put a lot of importance, warning pops up for me.

Setting a timer for a long period of time, i.e. multiple minutes, is a performance and correctness issue on Android as it keeps the timer module awake, and timers can only be called when the app is in the foreground. See (https://github.com/facebook/react-native/issues/12981) for more info. (Saw setTimeout with duration 111862ms)

Conflict with React

Hi, I'm re-open the issue #25 because of unfortunately not works, I upgraded to version:
"react-native-user-inactivity": "^1.0.1-beta.1",
and I continue receiving the error, and if I delete node_modules folder in the lib folder, it works again.

Support custom timers

The idea is that this package shouldn't be too opinionated about the setTimeout/clearTimeout-like functions that should be used to handle the activity timer.
This would fix #12, #15, #16 and #17 when paired with a native timer package, such as https://github.com/ocetnik/react-native-background-timer.

export interface TimeoutHandler<T> {
  /**
   * Timeout function that accepts two parameters:
   * a function and the timeout after which that function is fired.
   * If not provided, the default `timeoutFn` will be `setTimeout`.
   */
  setTimeout: (fn: () => void, timeout: number) => T;

  /**
   * Function that should be used to clear the effects of `timeoutFn` after
   * the `UserActivity` component is unmounted.
   */
  clearTimeout: (timeoutFn: T | undefined) => void;
}

const defaultTimeoutHandler: TimeoutHandler<number> = {
  setTimeout: (fn: () => void, timeout: number) => window.setTimeout(fn, timeout),
  clearTimeout: (timeoutFn: number | undefined) => { window.clearTimeout(timeoutFn) },
};

Not getting updated values from store inside onAction

I'm trying to logout user he/she us inactive for x number of minutes, I have two different different scenarios

  1. Onboarding screen before login/register
  2. Screens after login

So I am checking here if user is inactive on any of the Onboarding screens then I have to restart the Onboarding flow, If user login into the app then I have show the idle screen. For checking this status I am using the react native store but when onAction method call it always return the old store.

const performAutoLogout = async () => {
  if (!store.isUserLogin) {
    navigation.reset({
      index: 0,
      routes: [
        {
          name: 'Get Started',
        },
      ],
    })
  } else {
    navigation.reset({
      index: 0,
      routes: [
        {
          name: 'App Idle',
        },
      ],
    })
  }
}
return (
    <UserInactivity
      isActive={false}
      timeForInactivity={authTimeout}
      onAction={(isActive: boolean) => {
        // if timer exceeds x min then isActive = false and logout user
        if (!isActive) {
          performAutoLogout()
        }
      }}
    >
      <Stack.Navigator>
        {store.isUserLogin ? (
          <Stack.Group>
            <Stack.Screen name="Tabs">{() => <TabStack />}</Stack.Screen>
            <Stack.Screen name="Settings">{() => <SettingStack />}</Stack.Screen>
            <Stack.Screen name="Notifications" component={Notifications} />
            <Stack.Screen name="Idle Session" component={IdleSession} initialParams={{ setAuthenticated }} />
          </Stack.Group>
        ) : (
          <Stack.Group>
              <Stack.Screen name="Get Started" component={GetStarted} />
              <Stack.Screen name="Onboarding Screen" component={OnboardingScreen} />
              <Stack.Screen name="Terms" component={Terms} />
             <Stack.Screen name="Conditions" component={Conditions} />
          </Stack.Group>
        )}
      </Stack.Navigator>
    </UserInactivity>
  )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.