1import { useFocusEffect } from '@react-navigation/native';
2import { StackNavigationProp } from '@react-navigation/stack';
3import * as TaskManager from 'expo-task-manager';
4import React from 'react';
5import { ScrollView, StyleSheet, Text, View } from 'react-native';
6
7import Button from '../components/Button';
8import HeadingText from '../components/HeadingText';
9import MonoText from '../components/MonoText';
10
11export default function TaskManagerScreen(props: {
12  navigation: StackNavigationProp<{
13    BackgroundLocation: undefined;
14    Geofencing: undefined;
15    BackgroundFetch: undefined;
16  }>;
17}) {
18  const [tasks, setTasks] = React.useState<TaskManager.TaskManagerTask[]>([]);
19
20  const updateRegisteredTasks = async () => {
21    const tasks = await TaskManager.getRegisteredTasksAsync();
22    setTasks(tasks);
23  };
24
25  const onFocus = React.useCallback(() => {
26    let isActive = true;
27    TaskManager.getRegisteredTasksAsync().then((tasks) => {
28      if (isActive) setTasks(tasks);
29    });
30    return () => (isActive = false);
31  }, [setTasks]);
32
33  useFocusEffect(onFocus);
34
35  const unregisterTask = async (taskName: string) => {
36    await TaskManager.unregisterTaskAsync(taskName);
37    await updateRegisteredTasks();
38  };
39
40  const unregisterAllTasks = async () => {
41    await TaskManager.unregisterAllTasksAsync();
42    await updateRegisteredTasks();
43  };
44
45  const renderButtons = () => {
46    const buttons = tasks.map(({ taskName }) => {
47      return (
48        <Button
49          key={taskName}
50          style={styles.button}
51          title={`Unregister '${taskName}'`}
52          onPress={() => unregisterTask(taskName)}
53        />
54      );
55    });
56
57    return (
58      <View style={styles.buttons}>
59        {buttons}
60        {tasks!.length > 0 && (
61          <Button
62            style={styles.button}
63            buttonStyle={{ backgroundColor: 'red' }}
64            title="Unregister all tasks"
65            onPress={unregisterAllTasks}
66          />
67        )}
68        {renderNavigationButtons()}
69      </View>
70    );
71  };
72
73  const renderNavigationButtons = () => {
74    return (
75      <View>
76        <Text>
77          Note: this screen may not work properly for you, work is needed to investigate further and
78          improve it
79        </Text>
80        <Button
81          style={styles.button}
82          buttonStyle={{ backgroundColor: 'green' }}
83          title="Go to background location screen"
84          onPress={() => props.navigation.navigate('BackgroundLocation')}
85        />
86        <Button
87          style={styles.button}
88          buttonStyle={{ backgroundColor: 'green' }}
89          title="Go to geofencing screen"
90          onPress={() => props.navigation.navigate('Geofencing')}
91        />
92        <Button
93          style={styles.button}
94          buttonStyle={{ backgroundColor: 'green' }}
95          title="Go to background fetch screen"
96          onPress={() => props.navigation.navigate('BackgroundFetch')}
97        />
98      </View>
99    );
100  };
101
102  if (!tasks) {
103    return null;
104  }
105
106  return (
107    <ScrollView contentContainerStyle={styles.container}>
108      <HeadingText>Registered tasks</HeadingText>
109      <MonoText>{JSON.stringify(tasks, null, 2)}</MonoText>
110      {renderButtons()}
111    </ScrollView>
112  );
113}
114
115TaskManagerScreen.navigationOptions = {
116  title: 'TaskManager',
117};
118
119const styles = StyleSheet.create({
120  screen: {
121    flex: 1,
122  },
123  container: {
124    padding: 10,
125  },
126  buttons: {
127    padding: 10,
128  },
129  button: {
130    marginVertical: 10,
131  },
132});
133