Last active
October 7, 2023 16:26
-
-
Save HallexCosta/8e4ade25ad891e48fbbd4f51dbc5b496 to your computer and use it in GitHub Desktop.
Awesome Timer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useRef } from 'react'; | |
import { | |
SafeAreaView, | |
StyleSheet, | |
Text, | |
View, | |
TouchableHighlight, | |
} from 'react-native'; | |
import { Stopwatch } from 'react-native-stopwatch-timer'; | |
import * as Notifications from 'expo-notifications'; | |
const App = () => { | |
const [isStopwatchStart, setIsStopwatchStart] = useState(false); | |
const [resetStopwatch, setResetStopwatch] = useState(false); | |
const [expoPushToken, setExpoPushToken] = useState(''); | |
const [time, setTime] = useState(''); | |
const [notification, setNotification] = useState(false); | |
const notificationListener = useRef(); | |
const responseListener = useRef(); | |
Notifications.setNotificationHandler({ | |
handleNotification: async () => ({ | |
shouldShowAlert: true, | |
shouldPlaySound: false, | |
shouldSetBadge: false, | |
}), | |
}); | |
React.useEffect(() => { | |
// register for push notifications | |
// registerForPushNotificationsAsync().then(token => setExpoPushToken(token)); | |
// add category for timer controls (play, pause, and reset) | |
Notifications.setNotificationCategoryAsync( | |
'timer_controls', | |
[ | |
{ | |
identifier: 'play', | |
buttonTitle: 'Play ▷' | |
}, | |
{ | |
identifier: 'pause', | |
buttonTitle: 'Pause 𓊕', | |
}, | |
{ | |
identifier: 'reset', | |
buttonTitle: 'Reset', | |
} | |
] | |
) | |
// add listening on create new notification | |
notificationListener.current = Notifications.addNotificationReceivedListener(notification => { | |
setNotification(notification); | |
}); | |
// add listening on receive response from user (this is click of action buttons or the own notification) | |
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => { | |
switch (response.actionIdentifier) { | |
case 'play': | |
console.log('Played') | |
onStart() | |
break | |
case 'pause': | |
console.log('Paused') | |
onStop() | |
break | |
case 'reset': | |
console.log('Reseted') | |
onReset() | |
break | |
default: | |
break; | |
} | |
}); | |
// unsubscription notification listener and response listener | |
return () => { | |
Notifications.removeNotificationSubscription(notificationListener.current); | |
Notifications.removeNotificationSubscription(responseListener.current); | |
}; | |
}, []); | |
// declare hook for update notifcation always receive new time | |
React.useEffect(() => { | |
displayNotification() | |
}, [time]) | |
// handle display notification on device | |
async function displayNotification() { | |
const identifier = await Notifications.scheduleNotificationAsync({ | |
identifier: 'timer', | |
content: { | |
title: 'Awesome Timer', | |
body: `Time: ${time}`, | |
categoryIdentifier: 'timer_controls', | |
}, | |
trigger: null, | |
}) | |
await Notifications.cancelScheduledNotificationAsync(identifier) | |
} | |
// handle on click start timer | |
const onStart = () => { | |
displayNotification() | |
setIsStopwatchStart(true); | |
setResetStopwatch(false); | |
} | |
// handle on click stop timer | |
const onStop = () => { | |
setIsStopwatchStart(false); | |
setResetStopwatch(false); | |
} | |
// handle on click reset timer | |
const onReset = () => { | |
setIsStopwatchStart(false); | |
setResetStopwatch(true); | |
// schedulePushNotification() | |
} | |
// testing code - used to simulate notification cancel | |
// async function schedulePushNotification(time = 10) { | |
// const identifier = await Notifications.scheduleNotificationAsync({ | |
// identifier: 't', | |
// content: { | |
// title: "You've got mail! 📬", | |
// body: 'Here is the notification body: ' + time, | |
// data: {data: 'goes here'}, | |
// }, | |
// trigger: null, | |
// }); | |
// await Notifications.cancelScheduledNotificationAsync(identifier) | |
// if (time > 0) { | |
// const delay = (t) => new Promise((resolve) => setTimeout(resolve, t * 1000)) | |
// await delay(1) | |
// await schedulePushNotification(--time) | |
// return | |
// } | |
// } | |
// async function registerForPushNotificationsAsync() { | |
// let token; | |
// if (Platform.OS === 'android') { | |
// await Notifications.setNotificationChannelAsync('default', { | |
// name: 'default', | |
// importance: Notifications.AndroidImportance.MAX, | |
// vibrationPattern: [0, 250, 250, 250], | |
// lightColor: '#FF231F7C', | |
// }); | |
// } | |
// if (Device.isDevice) { | |
// const {status: existingStatus} = await Notifications.getPermissionsAsync(); | |
// let finalStatus = existingStatus; | |
// if (existingStatus !== 'granted') { | |
// const {status} = await Notifications.requestPermissionsAsync(); | |
// finalStatus = status; | |
// } | |
// if (finalStatus !== 'granted') { | |
// alert('Failed to get device push token for push notification!'); | |
// return; | |
// } | |
// token = (await Notifications.getExpoPushTokenAsync()).data; | |
// console.log(token); | |
// } else { | |
// alert('Must use a physical device for Push Notifications'); | |
// } | |
// return token; | |
// } | |
return ( | |
<SafeAreaView style={styles.container}> | |
<View style={styles.container}> | |
<Text style={styles.title}> | |
Example of React Native Timer and Stopwatch | |
</Text> | |
<View style={styles.sectionStyle}> | |
<Stopwatch | |
laps | |
secs | |
start={isStopwatchStart} | |
//To start | |
reset={resetStopwatch} | |
//To reset | |
options={options} | |
//options for the styling | |
getTime={(time) => setTime(time)} | |
/> | |
<TouchableHighlight | |
onPress={!isStopwatchStart ? onStart : onStop}> | |
<Text style={styles.buttonText}> | |
{!isStopwatchStart ? 'START' : 'STOP'} | |
</Text> | |
</TouchableHighlight> | |
<TouchableHighlight | |
onPress={onReset}> | |
<Text style={styles.buttonText}>RESET</Text> | |
</TouchableHighlight> | |
</View> | |
</View> | |
</SafeAreaView> | |
); | |
}; | |
export default App; | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
padding: 10, | |
justifyContent: 'center', | |
alignItems: 'center', | |
}, | |
title: { | |
textAlign: 'center', | |
fontSize: 20, | |
fontWeight: 'bold', | |
padding: 20, | |
}, | |
sectionStyle: { | |
flex: 1, | |
marginTop: 32, | |
alignItems: 'center', | |
justifyContent: 'center', | |
}, | |
buttonText: { | |
fontSize: 20, | |
marginTop: 10, | |
}, | |
}); | |
const options = { | |
container: { | |
backgroundColor: '#FF0000', | |
padding: 5, | |
borderRadius: 5, | |
width: 200, | |
alignItems: 'center', | |
}, | |
text: { | |
fontSize: 25, | |
color: '#FFF', | |
marginLeft: 7, | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment