eletrotupi / tcc/ commit / fe2deb4

frontend: basic notifications testing screen

Pedro Lucas Porcellis porcellis@eletrotupi.com · 4 months ago fe2deb48e4d91c97820de01dec6dd464c725329f Browse files
Parents 6360c22
Changed files
3
Additions
+154
Deletions
-1
frontend/app/(tabs)/_layout.tsx
1 1
import { Tabs, Redirect, router } from 'expo-router';
2 2
import React, { useEffect } from 'react';
3 3
import { View, ActivityIndicator } from 'react-native';
4 4

5 5
import { HapticTab } from '@/components/misc/haptic-tab';
6 6
import { IconSymbol } from '@/components/ui/icon-symbol';
7 7
import { Colors } from '@/constants/theme';
8 8
import { useColorScheme } from '@/hooks/use-color-scheme';
9 9
import { useAuth } from '@/context/AuthContext';
10 +
import * as Notifications from "expo-notifications";
10 11

11 12
export default function TabLayout() {
12 13
  const colorScheme = useColorScheme();
13 14
  const { isAuthenticated, isLoading } = useAuth();
14 15

15 16
  useEffect(() => {
16 17
    if (!isLoading && !isAuthenticated) {
17 18
      router.replace('/auth/login');
18 19
    }
19 20
  }, [isAuthenticated, isLoading]);
21 +

22 +
  // TODO: Store the notification in a hook ctx, then capture if was
23 +
  useEffect(() => {
24 +
    const subscription = Notifications.addNotificationResponseReceivedListener(response => {
25 +
      const screen = response.notification.request.content.data?.screen;
26 +

27 +
      if (screen === 'notifications') {
28 +
        router.push('/notifications');
29 +
      }
30 +
    });
31 +

32 +
    // Handle notification tap when app was already open
33 +
    Notifications.setNotificationHandler({
34 +
      handleNotification: async () => ({
35 +
        shouldShowAlert: true,
36 +
        shouldPlaySound: false,
37 +
        shouldSetBadge: false,
38 +
      }),
39 +
    });
40 +

41 +
    return () => subscription.remove();
42 +
  }, []);
20 43

21 44
  if (isLoading) {
22 45
    return (
23 46
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
24 47
        <ActivityIndicator size="large" />
79 102
        }}
80 103
      />
81 104
    </Tabs>
82 105
  );
83 106
}
frontend/app/(tabs)/new/index.tsx
1 1
import { useEffect, useState } from "react";
2 2
import { StyleSheet, View, Text, ActivityIndicator } from "react-native";
3 3

4 4
import { ThemedText } from "@/components/misc/themed-text";
5 5
import { ThemedView } from "@/components/misc/themed-view";
37 37
  const initQuickRegister = () => {
38 38
    // TODO: Set down on camelCase vs kebab case
39 39
    router.navigate(`/new/entry?initialMood=${mood}`);
40 40
  };
41 41

42 +
  const onNotificationPress = () => {
43 +
    router.push('/notifications');
44 +
  }
45 +

42 46
  return (
43 47
    <ScreenLayout
44 48
      userName={user.firstName}
45 49
      userAvatar={user.avatarURL}
46 -
      onNotificationPress={() => console.log("Notifications")}
50 +
      onNotificationPress={onNotificationPress}
47 51
      showNotificationBadge={true}
48 52
    >
49 53
      <Section>
50 54
        <SectionHeader
51 55
          title="Como você está hoje?"
185 189
    fontSize: 11,
186 190
    fontWeight: 600,
187 191
    lineHeight: 16.5,
188 192
  },
189 193
});
/dev/null → frontend/app/notifications.tsx
1 +
import {
2 +
  View,
3 +
  Text,
4 +
  StyleSheet,
5 +
  ScrollView,
6 +
  KeyboardAvoidingView,
7 +
  Platform,
8 +
  Alert,
9 +
} from 'react-native';
10 +

11 +
import {
12 +
  useState, useEffect
13 +
} from 'react';
14 +
import * as Notifications from 'expo-notifications';
15 +
import { useAuth } from "@/context/AuthContext";
16 +

17 +
import { StatusBar } from 'expo-status-bar';
18 +
import { SafeAreaView } from 'react-native-safe-area-context';
19 +
import { useThemeColor } from '@/hooks/use-theme-color';
20 +
import { Button } from '@/components/ui/Button';
21 +

22 +
export default function NotificationsPage() {
23 +
  const { user } = useAuth();
24 +
  const backgroundColor = useThemeColor({}, 'background');
25 +
  const [expoPushToken, setExpoPushToken] = useState(user.pushToken);
26 +
  const [notification, setNotification] = useState<Notifications.Notification | undefined>(
27 +
    undefined
28 +
  );
29 +

30 +
  useEffect(() => {
31 +
    const notificationListener = Notifications
32 +
    .addNotificationReceivedListener(notification => {
33 +
      setNotification(notification);
34 +
    });
35 +

36 +
    const responseListener = Notifications
37 +
    .addNotificationResponseReceivedListener(response => {
38 +
      console.log(response);
39 +
    });
40 +

41 +
    return () => {
42 +
      notificationListener.remove();
43 +
      responseListener.remove();
44 +
    };
45 +
  }, []);
46 +

47 +
  useEffect(() => {
48 +
    setExpoPushToken(user.pushToken)
49 +
  }, [user]);
50 +

51 +
  async function sendPushNotification(expoPushToken: string) {
52 +
    if (expoPushToken) {
53 +
      const message = {
54 +
        to: expoPushToken,
55 +
        sound: 'default',
56 +
        title: 'Oi meu querido',
57 +
        body: 'Vamo escutar um The Doors',
58 +
        data: { screen: 'notifications' },
59 +
      };
60 +

61 +
      const response = await fetch('https://exp.host/--/api/v2/push/send', {
62 +
        method: 'POST',
63 +
        headers: {
64 +
          Accept: 'application/json',
65 +
          'Accept-encoding': 'gzip, deflate',
66 +
          'Content-Type': 'application/json',
67 +
        },
68 +
        body: JSON.stringify(message),
69 +
      });
70 +
    }
71 +
  }
72 +

73 +
  return (
74 +
    <SafeAreaView style={[styles.container, { backgroundColor }]}>
75 +
      <StatusBar style={'dark'} />
76 +
      <KeyboardAvoidingView
77 +
        behavior='height'
78 +
        style={styles.keyboardView}
79 +
      >
80 +
        <ScrollView
81 +
          contentContainerStyle={styles.scrollContainer}
82 +
          showsVerticalScrollIndicator={false}
83 +
        >
84 +
        <View>
85 +
          <Text>
86 +
            Uma notificação!!!
87 +
          </Text>
88 +
        </View>
89 +

90 +
        <View style={{ alignItems: 'center', justifyContent: 'center' }}>
91 +
          <Text>Title: {notification && notification.request.content.title} </Text>
92 +
          <Text>Body: {notification && notification.request.content.body}</Text>
93 +
          <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text>
94 +
        </View>
95 +

96 +
        <Button
97 +
          title="Quer ver uma coisa?"
98 +
          onPress={async () => {
99 +
            await sendPushNotification(expoPushToken);
100 +
          }}
101 +
        />
102 +

103 +
        </ScrollView>
104 +
      </KeyboardAvoidingView>
105 +
    </SafeAreaView>
106 +
  );
107 +
}
108 +

109 +
const styles = StyleSheet.create({
110 +
  container: {
111 +
    flex: 1,
112 +
  },
113 +
  keyboardView: {
114 +
    flex: 1,
115 +
  },
116 +
  scrollContainer: {
117 +
    flexGrow: 1,
118 +
    paddingHorizontal: 24,
119 +
    justifyContent: 'start',
120 +
    minHeight: '100%',
121 +
  },
122 +
  header: {
123 +
    alignItems: 'left',
124 +
    marginBottom: 40,
125 +
  },
126 +
});