Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added new inactivity wrapper component #1283

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 22 additions & 19 deletions packages/legacy/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
AuthProvider,
ConfigurationProvider,
ErrorModal,
InactivityWrapper,
NetInfo,
NetworkProvider,
RootStack,
Expand Down Expand Up @@ -55,25 +56,27 @@ const App = () => {
<ConfigurationProvider value={defaultConfiguration}>
<AuthProvider>
<NetworkProvider>
<StatusBar
hidden={false}
barStyle="light-content"
backgroundColor={theme.ColorPallet.brand.primary}
translucent={false}
/>
<NetInfo />
<ErrorModal />
<TourProvider
homeTourSteps={homeTourSteps}
credentialsTourSteps={credentialsTourSteps}
credentialOfferTourSteps={credentialOfferTourSteps}
proofRequestTourSteps={proofRequestTourSteps}
overlayColor={'gray'}
overlayOpacity={0.7}
>
<RootStack />
</TourProvider>
<Toast topOffset={15} config={toastConfig} />
<InactivityWrapper>
<StatusBar
hidden={false}
barStyle="light-content"
backgroundColor={theme.ColorPallet.brand.primary}
translucent={false}
/>
<NetInfo />
<ErrorModal />
<TourProvider
homeTourSteps={homeTourSteps}
credentialsTourSteps={credentialsTourSteps}
credentialOfferTourSteps={credentialOfferTourSteps}
proofRequestTourSteps={proofRequestTourSteps}
overlayColor={'gray'}
overlayOpacity={0.7}
>
<RootStack />
</TourProvider>
<Toast topOffset={15} config={toastConfig} />
</InactivityWrapper>
</NetworkProvider>
</AuthProvider>
</ConfigurationProvider>
Expand Down
119 changes: 119 additions & 0 deletions packages/legacy/core/App/components/misc/InactivityWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { useAgent } from '@credo-ts/react-hooks'
import React, { PropsWithChildren, useCallback, useEffect, useRef } from 'react'
import { AppState, PanResponder, View } from 'react-native'
import { useAuth } from '../../contexts/auth'
import { useStore } from '../../contexts/store'
import { DispatchAction } from '../../contexts/reducers/store'
import { TOKENS, useServices } from '../../container-api'

export const LockOutTime = {
OneMinute: 1,
ThreeMinutes: 3,
FiveMinutes: 5,
Never: 0,
} as const

type InactivityWrapperProps = {
timeoutLength?: number // number of minutes before timeoutAction is triggered, a value of 0 will never trigger the timeoutAction and an undefined value will default to 5 minutes
}

const InactivityWrapper: React.FC<PropsWithChildren<InactivityWrapperProps>> = ({ children, timeoutLength }) => {
const [logger] = useServices([TOKENS.UTIL_LOGGER])
const [, dispatch] = useStore()
const { agent } = useAgent()
const { removeSavedWalletSecret } = useAuth()
const timeoutAsMilliseconds = (timeoutLength !== undefined ? timeoutLength : LockOutTime.OneMinute) * 60000
const inactivityTimer = useRef<NodeJS.Timeout | null>(null)
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponderCapture: () => {
// some user interaction detected, reset timeout
resetInactivityTimeout(timeoutAsMilliseconds)

// returns false so the PanResponder doesn't consume the touch event
return false
},
})
).current

const lockUserOut = useCallback(async () => {
try {
removeSavedWalletSecret()
await agent?.wallet.close()
} catch (error) {
logger.error(`Error closing agent wallet, ${error}`)
}

dispatch({
type: DispatchAction.DID_AUTHENTICATE,
payload: [{ didAuthenticate: false }],
})

dispatch({
type: DispatchAction.LOCKOUT_UPDATED,
payload: [{ displayNotification: true }],
})
}, [agent, removeSavedWalletSecret, dispatch, logger])

const clearTimer = useCallback(() => {
if (inactivityTimer.current) {
clearTimeout(inactivityTimer.current)
}
}, [])

const resetInactivityTimeout = useCallback(
(milliseconds: number) => {
// remove existing timeout
clearTimer()

// do not start timer if timeout is set to 0
if (milliseconds > 0) {
// create new timeout
inactivityTimer.current = setTimeout(async () => {
lockUserOut()
}, milliseconds)
}
},
[clearTimer, lockUserOut]
)

useEffect(() => {
// Setup listener for app state changes (background/ foreground movement)
const eventSubscription = AppState.addEventListener('change', (nextAppState) => {
if (AppState.currentState === 'active' && ['inactive', 'background'].includes(nextAppState)) {
if (nextAppState === 'inactive') {
// special case for iOS devices when a prompt is shown
return
}

// remove timer
clearTimer()
}

if (AppState.currentState === 'active' && ['active'].includes(nextAppState)) {
if (nextAppState === 'inactive') {
// special case for iOS devices when a prompt is shown
return
}

// app coming into the foreground is 'user activity', restart timer
resetInactivityTimeout(timeoutAsMilliseconds)
}
})

// initiate inactivity timer
resetInactivityTimeout(timeoutAsMilliseconds)

return () => {
clearTimer()
eventSubscription.remove()
}
})

return (
<View style={{ flex: 1 }} {...panResponder.panHandlers}>
{children}
</View>
)
}
export default InactivityWrapper
5 changes: 4 additions & 1 deletion packages/legacy/core/App/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import Scan from './screens/Scan'
import Onboarding from './screens/Onboarding'
import { PINRules, walletTimeout } from './constants'
import { CredentialListFooterProps } from './types/credential-list-footer'
import InactivityWrapper, { LockOutTime } from 'components/misc/InactivityWrapper'

export * from './navigators'
export * from './services/storage'
Expand Down Expand Up @@ -125,16 +126,18 @@ export {
credentialOfferTourSteps,
proofRequestTourSteps,
ButtonType,
IconButton,
ButtonLocation,
CheckBoxRow,
CredentialCard,
ContentGradient,
ErrorModal,
IconButton,
InactivityWrapper,
InfoTextBox,
InfoBox,
InfoBoxType,
Link,
LockOutTime,
ToastType,
toastConfig,
NetInfo,
Expand Down