forked from expo/react-conf-app
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBookmark.tsx
97 lines (86 loc) · 2.84 KB
/
Bookmark.tsx
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
import MaterialCommunityIcons from "@expo/vector-icons/build/MaterialCommunityIcons";
import * as Haptics from "expo-haptics";
import { Platform } from "react-native";
import Animated, {
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
import { TouchableOpacity } from "react-native-gesture-handler";
import * as Notifications from "expo-notifications";
import { useBookmarkStore } from "@/store/bookmarkStore";
import { theme } from "@/theme";
import { registerForPushNotificationsAsync } from "@/utils/registerForPushNotificationsAsync";
import { isPast, subMinutes } from "date-fns";
import { Session } from "@/types";
const AnimatedTouchableOpacity =
Animated.createAnimatedComponent(TouchableOpacity);
export function Bookmark({ session }: { session: Session }) {
const toggleBookmarked = useBookmarkStore((state) => state.toggleBookmarked);
const bookmarks = useBookmarkStore((state) => state.bookmarks);
const currentBookmark = bookmarks.find((b) => b.sessionId === session.id);
const scale = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const setNotification = async () => {
const fiveMinutesTillSession = subMinutes(new Date(session.startsAt), 5);
if (isPast(fiveMinutesTillSession)) {
return undefined;
}
const status = await registerForPushNotificationsAsync();
if (status === "granted") {
return Notifications.scheduleNotificationAsync({
content: {
title: `"${session.title}" starts in 5 minutes`,
data: {
url: `/talk/${session.id}`,
},
},
trigger: {
date: fiveMinutesTillSession,
},
});
}
};
const handlePress = async () => {
if (Platform.OS !== "web") {
Haptics.selectionAsync();
}
if (currentBookmark) {
if (currentBookmark?.notificationId) {
await Notifications.cancelScheduledNotificationAsync(
currentBookmark?.notificationId,
);
}
toggleBookmarked(session.id);
} else {
const notificationId = await setNotification();
toggleBookmarked(session.id, notificationId);
}
};
return (
<AnimatedTouchableOpacity
hitSlop={20}
onPress={() => {
if (Platform.OS !== "web" && !currentBookmark) {
Haptics.selectionAsync();
}
handlePress();
}}
onPressIn={() => {
scale.value = currentBookmark ? withTiming(0.8) : withTiming(1.6);
}}
onPressOut={() => {
scale.value = withTiming(1);
}}
style={animatedStyle}
>
<MaterialCommunityIcons
name={currentBookmark ? "bookmark-check" : "bookmark"}
size={24}
color={currentBookmark ? theme.colorWhite : `rgba(255, 255, 255, 0.5)`}
/>
</AnimatedTouchableOpacity>
);
}