Definitely going to need to work on the types here

This commit is contained in:
Gabriel Brown 2024-10-16 08:02:39 -05:00
parent 701315011b
commit c2858198ca
8 changed files with 538 additions and 0 deletions

View File

@ -0,0 +1,78 @@
import React, { useCallback, useReducer } from 'react';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import { Alert, Linking, Platform, StyleSheet } from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import {
GiftedChat,
IMessage,
Send,
SendProps,
SystemMessage,
} from 'react-native-gifted-chat';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import AccessoryBar from '@/components/chat/AccessoryBar';
import CustomActions from '@/components/chat/CustomActions';
import CustomView from '@/components/chat/CustomView';
import NavBar from '@/components/chat/NavBar';
import earlierMessages from '@/components/chat/data/earlierMessages';
import messages from '@/components/chat/data/messages';
import * as Clipboard from 'expo-clipboard';
import {
GCUser,
GCState,
GCStateAction,
ActionKind,
GCMessage
} from '@/constants/Types';
const tempUser: GCUser = {
_id: 1,
name: 'Developer',
};
const reducer = (state: GCState, action: GCStateAction) => {
switch (action.type) {
case ActionKind.SEND_MESSAGE: {
return {
...state,
step: state.step + 1,
messages: action.payload,
};
}
case ActionKind.LOAD_EARLIER_MESSAGES: {
return {
...state,
loadEarlier: true,
isLoadingEarlier: false,
messages: action.payload,
};
}
case ActionKind.LOAD_EARLIER_START: {
return {
...state,
isLoadingEarlier: true,
}
}
case ActionKind.SET_IS_TYPING: {
return {
...state,
isTyping: action.payload,
}
}
}
};
const MessagesScreen = () => {
const [state, dispatch] = useReducer(reducer, {
messages: messages,
step: 0,
loadEarlier: true,
isLoadingEarlier: false,
isTyping: false,
})
const onSend = useCallback((messages: GCMessage[]) => {
const sentMessages = [{ ...messages[0], sent: true, received: true }]
};
export default MessagesScreen;

View File

@ -0,0 +1,83 @@
import React, { useCallback } from 'react';
import * as Linking from 'expo-linking';
import {
Platform,
StyleSheet,
StyleProp,
ViewStyle
} from 'react-native';
import { ThemedText, ThemedView } from '@/components/theme/Theme';
import MapView from 'react-native-maps';
import { TouchableOpacity } from 'react-native-gesture-handler';
type Props = {
currentMessage: any;
containerStyle?: StyleProp<ViewStyle>;
mapViewStyle?: StyleProp<ViewStyle>;
};
const CustomView = ({ currentMessage, containerStyle, mapViewStyle }: Props) => {
const openMapAsync = useCallback(async () => {
if (Platform.OS === 'web') {
alert('Opening the map is not supported.');
return;
}
const {location = {} } = currentMessage;
const url = Platform.select({
ios: `http://maps.apple.com/?ll=${location.latitude},${location.longitude}`,
default: `http://maps.google.com/?q=${location.latitude},${location.longitude}`,
});
try {
const supported = await Linking.canOpenURL(url);
if (supported) return Linking.openURL(url);
else alert('Opening the map is not supported.');
} catch (error) {
console.log('Could not open link!', error.message);
alert(error.message);
}
}, [currentMessage]);
if (currentMessage.location) {
return (
<TouchableOpacity
style={[styles.container, containerStyle]}
onPress={openMapAsync}
>
{Platform.OS !== 'web'
? (
<MapView
style={[styles.mapView, mapViewStyle]}
region={{
latitude: currentMessage.location.latitude,
longitude: currentMessage.location.longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
scrollEnabled={false}
zoomEnabled={false}
/>
)
: (
<ThemedView style={{ padding: 15 }}>
<ThemedText style={{ color: 'tomato', fontWeight: 'bold' }}>
Map not in web yet, sorry!
</ThemedText>
</ThemedView>
)}
</TouchableOpacity>
);
}
return null;
};
export default CustomView;
const styles = StyleSheet.create({
container: {
},
mapView: {
width: 150,
height: 100,
borderRadius: 13,
margin: 3,
},
});

View File

@ -0,0 +1,20 @@
import React from 'react';
import { ThemedText, ThemedView } from '../theme/Theme';
import { Platform, StyleSheet } from 'react-native';
const NavBar = () => {
if (Platform.OS === 'web') return null;
return (
<ThemedView style={styles.container}>
<ThemedText>💬 Chat{'\n'}</ThemedText>
</ThemedView>
);
};
export default NavBar;
const styles = StyleSheet.create({
container: {
alignItems: 'center',
paddingTop: 10,
},
});

View File

@ -0,0 +1,129 @@
export default () => [
{
_id: Math.round(Math.random() * 1000000),
text:
'It uses the same design as React, letting you compose a rich mobile UI from declarative components https://facebook.github.io/react-native/',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text:
'It uses the same design as React, letting you compose a rich mobile UI from declarative components https://facebook.github.io/react-native/',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text:
'It uses the same design as React, letting you compose a rich mobile UI from declarative components https://facebook.github.io/react-native/',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text:
'It uses the same design as React, letting you compose a rich mobile UI from declarative components https://facebook.github.io/react-native/',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'React Native lets you build mobile apps using only JavaScript',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: Math.round(Math.random() * 1000000),
text: 'This is a system message.',
createdAt: new Date(Date.UTC(2016, 7, 30, 17, 20, 0)),
system: true,
},
]

View File

@ -0,0 +1,168 @@
export default [
{
_id: 9,
text: '#awesome 3',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 8,
text: '#awesome 2',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 7,
text: '#awesome',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 6,
text: 'Paris',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
},
image:
'https://www.xtrafondos.com/wallpapers/torre-eiffel-en-paris-415.jpg',
sent: true,
received: true,
},
{
_id: 5,
text: 'Send me a picture!',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 4,
text: '',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
},
sent: true,
received: true,
location: {
latitude: 48.864601,
longitude: 2.398704,
},
},
{
_id: 3,
text: 'Where are you?',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 2,
text: 'Yes, and I use #GiftedChat!',
createdAt: new Date(),
user: {
_id: 2,
name: 'React Native',
},
sent: true,
received: true,
},
{
_id: 1,
text: 'Are you building a chat app?',
createdAt: new Date(),
user: {
_id: 1,
name: 'Developer',
},
},
{
_id: 10,
text: 'This is a quick reply. Do you love Gifted Chat? (radio) KEEP IT',
createdAt: new Date(),
quickReplies: {
type: 'radio', // or 'checkbox',
keepIt: true,
values: [
{
title: '😋 Yes',
value: 'yes',
},
{
title:
'📷 Yes, let me show you with a picture! Again let me show you with a picture!',
value: 'yes_picture',
},
{
title: '😞 Nope. What?',
value: 'no',
},
],
},
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 20,
text: 'This is a quick reply. Do you love Gifted Chat? (checkbox)',
createdAt: new Date(),
quickReplies: {
type: 'checkbox', // or 'checkbox',
values: [
{
title: 'Yes',
value: 'yes',
},
{
title: 'Yes, let me show you with a picture!',
value: 'yes_picture',
},
{
title: 'Nope. What?',
value: 'no',
},
],
},
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 30,
createdAt: new Date(),
video: 'https://media.giphy.com/media/3o6ZthZjk09Xx4ktZ6/giphy.mp4',
user: {
_id: 2,
name: 'React Native',
},
},
{
_id: 31,
createdAt: new Date(),
audio:
'https://file-examples.com/wp-content/uploads/2017/11/file_example_MP3_700KB.mp3',
user: {
_id: 2,
name: 'React Native',
},
},
]

View File

@ -123,9 +123,28 @@ export type GCMessage = {
pending?: boolean; pending?: boolean;
quickReplies?: GCQuickReplies; quickReplies?: GCQuickReplies;
}; };
export type GCState = {
messages: any[];
step: number;
loadEarlier?: boolean;
isLoadingEarlier?: boolean;
isTyping: boolean;
};
export enum ActionKind {
SEND_MESSAGE = 'SEND_MESSAGE',
LOAD_EARLIER_MESSAGES = 'LOAD_EARLIER_MESSAGES',
LOAD_EARLIER_START = 'LOAD_EARLIER_START',
SET_IS_TYPING = 'SET_IS_TYPING',
// LOAD_EARLIER_END = 'LOAD_EARLIER_END',
};
export type GCStateAction = {
type: ActionKind;
payload?: any;
};
export type NotificationMessage = { export type NotificationMessage = {
sound?: string; sound?: string;
title: string; title: string;
body: string; body: string;
data?: any; data?: any;
}; };

View File

@ -18,6 +18,7 @@
"@react-navigation/native": "^6.0.2", "@react-navigation/native": "^6.0.2",
"expo": "~51.0.28", "expo": "~51.0.28",
"expo-apple-authentication": "~6.4.2", "expo-apple-authentication": "~6.4.2",
"expo-clipboard": "~6.0.3",
"expo-constants": "~16.0.2", "expo-constants": "~16.0.2",
"expo-device": "~6.0.2", "expo-device": "~6.0.2",
"expo-font": "~12.0.9", "expo-font": "~12.0.9",
@ -38,6 +39,7 @@
"react-native-gesture-handler": "~2.16.1", "react-native-gesture-handler": "~2.16.1",
"react-native-get-random-values": "~1.11.0", "react-native-get-random-values": "~1.11.0",
"react-native-gifted-chat": "^2.6.4", "react-native-gifted-chat": "^2.6.4",
"react-native-maps": "1.14.0",
"react-native-reanimated": "~3.10.1", "react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5", "react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1", "react-native-screens": "3.31.1",

39
pnpm-lock.yaml generated
View File

@ -20,6 +20,9 @@ importers:
expo-apple-authentication: expo-apple-authentication:
specifier: ~6.4.2 specifier: ~6.4.2
version: 6.4.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))) version: 6.4.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
expo-clipboard:
specifier: ~6.0.3
version: 6.0.3(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
expo-constants: expo-constants:
specifier: ~16.0.2 specifier: ~16.0.2
version: 16.0.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))) version: 16.0.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
@ -80,6 +83,9 @@ importers:
react-native-gifted-chat: react-native-gifted-chat:
specifier: ^2.6.4 specifier: ^2.6.4
version: 2.6.4(react-native-get-random-values@1.11.0(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0)))(react-native-reanimated@3.10.1(@babel/core@7.25.8)(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0) version: 2.6.4(react-native-get-random-values@1.11.0(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0)))(react-native-reanimated@3.10.1(@babel/core@7.25.8)(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.5(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0)
react-native-maps:
specifier: 1.14.0
version: 1.14.0(react-native-web@0.19.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0)
react-native-reanimated: react-native-reanimated:
specifier: ~3.10.1 specifier: ~3.10.1
version: 3.10.1(@babel/core@7.25.8)(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0) version: 3.10.1(@babel/core@7.25.8)(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0)
@ -1373,6 +1379,9 @@ packages:
'@types/cookie@0.6.0': '@types/cookie@0.6.0':
resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
'@types/geojson@7946.0.14':
resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==}
'@types/graceful-fs@4.1.9': '@types/graceful-fs@4.1.9':
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
@ -2306,6 +2315,11 @@ packages:
peerDependencies: peerDependencies:
expo: '*' expo: '*'
expo-clipboard@6.0.3:
resolution: {integrity: sha512-RIKDsuHkYfaspifbFpVC8sBVFKR05L7Pj7mU2/XkbrW9m01OBNvdpGraXEMsTFCx97xMGsZpEw9pPquL4j4xVg==}
peerDependencies:
expo: '*'
expo-constants@16.0.2: expo-constants@16.0.2:
resolution: {integrity: sha512-9tNY3OVO0jfiMzl7ngb6IOyR5VFzNoN5OOazUWoeGfmMqVB5kltTemRvKraK9JRbBKIw+SOYLEmF0sEqgFZ6OQ==} resolution: {integrity: sha512-9tNY3OVO0jfiMzl7ngb6IOyR5VFzNoN5OOazUWoeGfmMqVB5kltTemRvKraK9JRbBKIw+SOYLEmF0sEqgFZ6OQ==}
peerDependencies: peerDependencies:
@ -3971,6 +3985,17 @@ packages:
react: '>=16.8.0' react: '>=16.8.0'
react-native: '>=0.61.0' react-native: '>=0.61.0'
react-native-maps@1.14.0:
resolution: {integrity: sha512-ai7h4UdRLGPFCguz1fI8n4sKLEh35nZXHAH4nSWyAeHGrN8K9GjICu9Xd4Q5Ok4h+WwrM6Xz5pGbF3Qm1tO6iQ==}
engines: {node: '>=18'}
peerDependencies:
react: '>= 17.0.1'
react-native: '>= 0.64.3'
react-native-web: '>= 0.11'
peerDependenciesMeta:
react-native-web:
optional: true
react-native-parsed-text@0.0.22: react-native-parsed-text@0.0.22:
resolution: {integrity: sha512-hfD83RDXZf9Fvth3DowR7j65fMnlqM9PpxZBGWkzVcUTFtqe6/yPcIoIAgrJbKn6YmtzkivmhWE2MCE4JKBXrQ==} resolution: {integrity: sha512-hfD83RDXZf9Fvth3DowR7j65fMnlqM9PpxZBGWkzVcUTFtqe6/yPcIoIAgrJbKn6YmtzkivmhWE2MCE4JKBXrQ==}
peerDependencies: peerDependencies:
@ -7017,6 +7042,8 @@ snapshots:
'@types/cookie@0.6.0': {} '@types/cookie@0.6.0': {}
'@types/geojson@7946.0.14': {}
'@types/graceful-fs@4.1.9': '@types/graceful-fs@4.1.9':
dependencies: dependencies:
'@types/node': 22.7.5 '@types/node': 22.7.5
@ -8032,6 +8059,10 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
expo-clipboard@6.0.3(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))):
dependencies:
expo: 51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))
expo-constants@16.0.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))): expo-constants@16.0.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))):
dependencies: dependencies:
'@expo/config': 9.0.4 '@expo/config': 9.0.4
@ -10082,6 +10113,14 @@ snapshots:
react: 18.2.0 react: 18.2.0
react-native: 0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0) react-native: 0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0)
react-native-maps@1.14.0(react-native-web@0.19.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0):
dependencies:
'@types/geojson': 7946.0.14
react: 18.2.0
react-native: 0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0)
optionalDependencies:
react-native-web: 0.19.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
react-native-parsed-text@0.0.22(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0): react-native-parsed-text@0.0.22(react-native@0.74.5(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))(@types/react@18.2.79)(react@18.2.0))(react@18.2.0):
dependencies: dependencies:
prop-types: 15.8.1 prop-types: 15.8.1