-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathTime.js
More file actions
143 lines (134 loc) · 5.38 KB
/
Copy pathTime.js
File metadata and controls
143 lines (134 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import React, { useEffect, useState, useRef } from 'react';
import { View, Text, Button, TouchableOpacity, Alert, AppState } from 'react-native';
import * as Location from 'expo-location';
import * as Notifications from 'expo-notifications';
import * as TaskManager from 'expo-task-manager';
import * as BackgroundFetch from 'expo-background-fetch';
const GH_KEY = "38b2096b-51cc-428e-a112-4ba88e6c838f"; // Replace with your actual GraphHopper API key
const TASK_NAME = 'tracker-task';
export default function Time({ route, navigation }) {
const { destination } = route.params;
const [currentLocation, setCurrentLocation] = useState(null);
const [userDefined, setUserDefined] = useState(10);
const [alarmSet, setAlarmSet] = useState(false);
const appState = useRef(AppState.currentState);
// Get current location
useEffect(() => {
(async () => {
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
Alert.alert('Permission to access location was denied');
return;
}
let location = await Location.getCurrentPositionAsync({});
setCurrentLocation(location.coords);
})();
}, []);
// Listen for notification response to navigate to alarm screen
useEffect(() => {
const subscription = Notifications.addNotificationResponseReceivedListener(response => {
navigation.navigate('Alarm', { destination });
});
return () => subscription.remove();
}, [navigation, destination]);
// Clean up background task when leaving screen
useEffect(() => {
return () => {
BackgroundFetch.unregisterTaskAsync(TASK_NAME).catch(() => {});
};
}, []);
// Function to calculate duration
const getTravelDuration = async (from, to) => {
const point1 = `${from.latitude},${from.longitude}`;
const point2 = `${to.latitude},${to.longitude}`;
const url = `https://graphhopper.com/api/1/route?point=${point1}&point=${point2}&vehicle=car&locale=en&calc_points=false&key=${GH_KEY}`;
try {
const response = await fetch(url);
const data = await response.json();
if (data.paths && data.paths.length > 0) {
return data.paths[0].time / 60000; // minutes
}
return null;
} catch {
return null;
}
};
// Set alarm and register background task
const setAlarm = async () => {
if (!currentLocation) {
Alert.alert('Location not ready');
return;
}
await Notifications.requestPermissionsAsync();
await Location.startLocationUpdatesAsync(TASK_NAME, {
accuracy: Location.Accuracy.Highest,
distanceInterval: 100, // meters
deferredUpdatesInterval: 60000, // 1 min
showsBackgroundLocationIndicator: true,
});
await BackgroundFetch.registerTaskAsync(TASK_NAME, {
minimumInterval: 60, // seconds
stopOnTerminate: false,
startOnBoot: true,
});
global.trackerParams = {
destination,
userDefined,
navigation,
};
setAlarmSet(true);
Alert.alert('Alarm Set', `You will be notified when you are within ${userDefined} minutes of your destination.`);
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>
Current Location: {currentLocation ? `${currentLocation.latitude}, ${currentLocation.longitude}` : 'Fetching...'}
</Text>
<Text>
Destination: {destination.latitude}, {destination.longitude}
</Text>
<View style={{ flexDirection: 'row', marginVertical: 20 }}>
<TouchableOpacity onPress={() => setUserDefined(10)} style={{ marginRight: 10, backgroundColor: userDefined === 10 ? '#007AFF' : '#ccc', padding: 10 }}>
<Text style={{ color: 'white' }}>10 min</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => setUserDefined(15)} style={{ backgroundColor: userDefined === 15 ? '#007AFF' : '#ccc', padding: 10 }}>
<Text style={{ color: 'white' }}>15 min</Text>
</TouchableOpacity>
</View>
<Button title={alarmSet ? "Alarm Set" : "Set Alarm"} onPress={setAlarm} disabled={alarmSet} />
</View>
);
}
// Background Task definition
TaskManager.defineTask(TASK_NAME, async ({ data, error }) => {
try {
const location = await Location.getCurrentPositionAsync({});
const params = global.trackerParams;
if (!params) return BackgroundFetch.Result.NoData;
const { destination, userDefined } = params;
const point1 = `${location.coords.latitude},${location.coords.longitude}`;
const point2 = `${destination.latitude},${destination.longitude}`;
const url = `https://graphhopper.com/api/1/route?point=${point1}&point=${point2}&vehicle=car&locale=en&calc_points=false&key=${GH_KEY}`;
const response = await fetch(url);
const dataJson = await response.json();
if (dataJson.paths && dataJson.paths.length > 0) {
const minutes = dataJson.paths[0].time / 60000;
if (minutes <= userDefined) {
await Notifications.scheduleNotificationAsync({
content: {
title: "Destination Nearby",
body: "You are within your selected threshold!",
sound: true,
data: { alarm: true }
},
trigger: null,
});
await BackgroundFetch.unregisterTaskAsync(TASK_NAME);
return BackgroundFetch.Result.NewData;
}
}
return BackgroundFetch.Result.NoData;
} catch (e) {
return BackgroundFetch.Result.Failed;
}
});