Almost done with rewrite
This commit is contained in:
parent
5549cbbe10
commit
701315011b
52
components/chat/AccessoryBar.tsx
Normal file
52
components/chat/AccessoryBar.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { MaterialIcons } from '@expo/vector-icons';
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, TouchableOpacity } from 'react-native';
|
||||||
|
import { ThemedView } from '@/components/theme/Theme';
|
||||||
|
import {
|
||||||
|
getLocationAsync,
|
||||||
|
pickImageAsync,
|
||||||
|
takePictureAsync,
|
||||||
|
} from '@/components/chat/mediaUtils';
|
||||||
|
|
||||||
|
export default class AccessoryBar extends React.Component<any> {
|
||||||
|
render () {
|
||||||
|
const { onSend, isTyping } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemedView style={styles.container}>
|
||||||
|
<Button onPress={() => pickImageAsync(onSend)} name='photo' />
|
||||||
|
<Button onPress={() => takePictureAsync(onSend)} name='camera' />
|
||||||
|
<Button onPress={() => getLocationAsync(onSend)} name='my-location' />
|
||||||
|
<Button
|
||||||
|
onPress={() => {
|
||||||
|
isTyping()
|
||||||
|
}}
|
||||||
|
name='chat'
|
||||||
|
/>
|
||||||
|
</ThemedView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Button = ({
|
||||||
|
onPress,
|
||||||
|
size = 30,
|
||||||
|
color = 'rgba(255,255,255,0.8)',
|
||||||
|
...props
|
||||||
|
}) => (
|
||||||
|
<TouchableOpacity onPress={onPress}>
|
||||||
|
<MaterialIcons size={size} color={color} {...props} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
height: 45,
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
alignItems: 'center',
|
||||||
|
borderTopWidth: StyleSheet.hairlineWidth,
|
||||||
|
borderTopColor: 'rgba(255,255,255,0.3)',
|
||||||
|
},
|
||||||
|
});
|
109
components/chat/CustomActions.tsx
Normal file
109
components/chat/CustomActions.tsx
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import {
|
||||||
|
StyleProp,
|
||||||
|
ViewStyle,
|
||||||
|
TextStyle,
|
||||||
|
StyleSheet,
|
||||||
|
TouchableOpacity
|
||||||
|
} from 'react-native';
|
||||||
|
import { ThemedText, ThemedView } from '@/components/theme/Theme';
|
||||||
|
import { useActionSheet } from '@expo/react-native-action-sheet';
|
||||||
|
import {
|
||||||
|
getLocationAsync,
|
||||||
|
pickImageAsync,
|
||||||
|
takePictureAsync,
|
||||||
|
} from '@/components/chat/mediaUtils';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
renderIcon?: () => React.ReactNode;
|
||||||
|
wrapperStyle?: StyleProp<ViewStyle>;
|
||||||
|
containerStyle?: StyleProp<ViewStyle>;
|
||||||
|
iconTextStyle?: StyleProp<TextStyle>;
|
||||||
|
onSend: (messages: unknown) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomActions = ({
|
||||||
|
renderIcon,
|
||||||
|
iconTextStyle,
|
||||||
|
containerStyle,
|
||||||
|
wrapperStyle,
|
||||||
|
onSend,
|
||||||
|
}: Props) => {
|
||||||
|
const { showActionSheetWithOptions } = useActionSheet();
|
||||||
|
const onActionPress = useCallback(() => {
|
||||||
|
const options = [
|
||||||
|
'Choose From Library',
|
||||||
|
'Take Picture',
|
||||||
|
'Send Location',
|
||||||
|
'Cancel',
|
||||||
|
];
|
||||||
|
const cancelButtonIndex = options.length - 1;
|
||||||
|
showActionSheetWithOptions(
|
||||||
|
{
|
||||||
|
options,
|
||||||
|
cancelButtonIndex,
|
||||||
|
},
|
||||||
|
async (buttonIndex) => {
|
||||||
|
switch (buttonIndex) {
|
||||||
|
case 0:
|
||||||
|
pickImageAsync(onSend);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
takePictureAsync(onSend);
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
getLocationAsync(onSend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}, [showActionSheetWithOptions, onSend]);
|
||||||
|
|
||||||
|
const renderIconComponent = useCallback(() => {
|
||||||
|
if (renderIcon) return renderIcon();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemedView style={[styles.wrapper, wrapperStyle]}>
|
||||||
|
<ThemedText style={[styles.iconText, iconTextStyle]}>
|
||||||
|
+
|
||||||
|
</ThemedText>
|
||||||
|
</ThemedView>
|
||||||
|
);
|
||||||
|
}, [renderIcon, wrapperStyle, iconTextStyle]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.container, containerStyle]}
|
||||||
|
onPress={onActionPress}
|
||||||
|
>
|
||||||
|
{renderIconComponent()}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default CustomActions
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: 26,
|
||||||
|
height: 26,
|
||||||
|
marginLeft: 10,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
borderRadius: 13,
|
||||||
|
borderColor: '#b2b2b2',
|
||||||
|
borderWidth: 2,
|
||||||
|
flex: 1,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
iconText: {
|
||||||
|
color: '#b2b2b2',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 16,
|
||||||
|
lineHeight: 16,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
})
|
0
components/chat/CustomView.tsx
Normal file
0
components/chat/CustomView.tsx
Normal file
0
components/chat/NavBar.tsx
Normal file
0
components/chat/NavBar.tsx
Normal file
0
components/chat/data/earlierMessages.js
Normal file
0
components/chat/data/earlierMessages.js
Normal file
0
components/chat/data/messages.js
Normal file
0
components/chat/data/messages.js
Normal file
65
components/chat/mediaUtils.ts
Normal file
65
components/chat/mediaUtils.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { Alert } from 'react-native';
|
||||||
|
import * as Linking from 'expo-linking';
|
||||||
|
import * as Location from 'expo-location';
|
||||||
|
import * as Permissions from 'expo-permissions';
|
||||||
|
import * as ImagePicker from 'expo-image-picker';
|
||||||
|
|
||||||
|
export const getPermissionAsync = async (
|
||||||
|
permission: Permissions.PermissionType) => {
|
||||||
|
const {status} = await Permissions.askAsync(permission);
|
||||||
|
if (status !== 'granted') {
|
||||||
|
const permissionName = permission.toLowerCase().replace('_', ' ');
|
||||||
|
Alert.alert(
|
||||||
|
`Cannot access ${permissionName}`,
|
||||||
|
`If you would like to use this feature, you will need to enable ` +
|
||||||
|
`the ${permissionName} permission in your phone's settings.`,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
text: 'Let\'s go!',
|
||||||
|
onPress: () => Linking.openURL('app-settings:'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Nevermind',
|
||||||
|
onPress: () => {},
|
||||||
|
style: 'cancel'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{ cancelable: true }
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLocationAsync = async (
|
||||||
|
onSend: (locations: { location: Location.LocationObjectCoords }[]) => void) => {
|
||||||
|
const response = await Location.requestForegroundPermissionsAsync();
|
||||||
|
if (!response.granted) return;
|
||||||
|
const location = await Location.getCurrentPositionAsync();
|
||||||
|
if (!location) return;
|
||||||
|
onSend([{ location: location.coords }]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const pickImageAsync = async (onSend: (images: {image: string}[]) => void) => {
|
||||||
|
const response = await ImagePicker.requestMediaLibraryPermissionsAsync();
|
||||||
|
if (!response.granted) return;
|
||||||
|
const result = await ImagePicker.launchImageLibraryAsync({
|
||||||
|
allowsEditing: true,
|
||||||
|
aspect: [4, 3],
|
||||||
|
});
|
||||||
|
if (result.canceled) return;
|
||||||
|
const images = result.assets.map(({ uri: image }) => ({ image }));
|
||||||
|
onSend(images);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const takePictureAsync = async (onSend: (images: {image: string}[]) => void) => {
|
||||||
|
const response = await ImagePicker.requestCameraPermissionsAsync();
|
||||||
|
if (!response.granted) return;
|
||||||
|
const result = await ImagePicker.launchCameraAsync({
|
||||||
|
allowsEditing: true,
|
||||||
|
aspect: [4, 3],
|
||||||
|
});
|
||||||
|
if (result.canceled) return;
|
||||||
|
const images = result.assets.map(({ uri: image }) => ({ image }));
|
||||||
|
onSend(images);
|
||||||
|
};
|
@ -1,26 +1,27 @@
|
|||||||
/**
|
// Dark mode colors
|
||||||
* Below are the colors that are used in the app. The colors are defined in the light and dark mode.
|
const dark = '#2e2f3d';
|
||||||
* There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const tintColorLight = '#0a7ea4';
|
|
||||||
const tintColorDark = '#fff';
|
const tintColorDark = '#fff';
|
||||||
|
const iconColorDark = '#9BA1A6';
|
||||||
|
// Light mode colors
|
||||||
|
const light = '#ECEDEE';
|
||||||
|
const tintColorLight = '#0a7ea4';
|
||||||
|
const iconColorLight = '#687076';
|
||||||
|
|
||||||
export const Colors = {
|
export const Colors = {
|
||||||
light: {
|
light: {
|
||||||
text: '#11181C',
|
text: dark,
|
||||||
background: '#fff',
|
background: light,
|
||||||
tint: tintColorLight,
|
tint: tintColorLight,
|
||||||
icon: '#687076',
|
icon: iconColorLight,
|
||||||
tabIconDefault: '#687076',
|
tabIconDefault: iconColorLight,
|
||||||
tabIconSelected: tintColorLight,
|
tabIconSelected: tintColorLight,
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
text: '#ECEDEE',
|
text: dark,
|
||||||
background: '#151718',
|
background: light,
|
||||||
tint: tintColorDark,
|
tint: tintColorDark,
|
||||||
icon: '#9BA1A6',
|
icon: iconColorDark,
|
||||||
tabIconDefault: '#9BA1A6',
|
tabIconDefault: iconColorDark,
|
||||||
tabIconSelected: tintColorDark,
|
tabIconSelected: tintColorDark,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
"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",
|
||||||
|
"expo-image-picker": "~15.0.7",
|
||||||
"expo-linking": "~6.3.1",
|
"expo-linking": "~6.3.1",
|
||||||
"expo-location": "~17.0.1",
|
"expo-location": "~17.0.1",
|
||||||
"expo-notifications": "~0.28.18",
|
"expo-notifications": "~0.28.18",
|
||||||
|
"expo-permissions": "^14.4.0",
|
||||||
"expo-router": "~3.5.23",
|
"expo-router": "~3.5.23",
|
||||||
"expo-secure-store": "~13.0.2",
|
"expo-secure-store": "~13.0.2",
|
||||||
"expo-splash-screen": "~0.27.5",
|
"expo-splash-screen": "~0.27.5",
|
||||||
|
34
pnpm-lock.yaml
generated
34
pnpm-lock.yaml
generated
@ -29,6 +29,9 @@ importers:
|
|||||||
expo-font:
|
expo-font:
|
||||||
specifier: ~12.0.9
|
specifier: ~12.0.9
|
||||||
version: 12.0.10(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
version: 12.0.10(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
|
expo-image-picker:
|
||||||
|
specifier: ~15.0.7
|
||||||
|
version: 15.0.7(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
expo-linking:
|
expo-linking:
|
||||||
specifier: ~6.3.1
|
specifier: ~6.3.1
|
||||||
version: 6.3.1(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
version: 6.3.1(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
@ -38,6 +41,9 @@ importers:
|
|||||||
expo-notifications:
|
expo-notifications:
|
||||||
specifier: ~0.28.18
|
specifier: ~0.28.18
|
||||||
version: 0.28.18(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
version: 0.28.18(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
|
expo-permissions:
|
||||||
|
specifier: ^14.4.0
|
||||||
|
version: 14.4.0(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
expo-router:
|
expo-router:
|
||||||
specifier: ~3.5.23
|
specifier: ~3.5.23
|
||||||
version: 3.5.23(k73ovpznblgccxklktj7qyihii)
|
version: 3.5.23(k73ovpznblgccxklktj7qyihii)
|
||||||
@ -2320,6 +2326,16 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
expo: '*'
|
expo: '*'
|
||||||
|
|
||||||
|
expo-image-loader@4.7.0:
|
||||||
|
resolution: {integrity: sha512-cx+MxxsAMGl9AiWnQUzrkJMJH4eNOGlu7XkLGnAXSJrRoIiciGaKqzeaD326IyCTV+Z1fXvIliSgNW+DscvD8g==}
|
||||||
|
peerDependencies:
|
||||||
|
expo: '*'
|
||||||
|
|
||||||
|
expo-image-picker@15.0.7:
|
||||||
|
resolution: {integrity: sha512-u8qiPZNfDb+ap6PJ8pq2iTO7JKX+ikAUQ0K0c7gXGliKLxoXgDdDmXxz9/6QdICTshJBJlBvI0MwY5NWu7A/uw==}
|
||||||
|
peerDependencies:
|
||||||
|
expo: '*'
|
||||||
|
|
||||||
expo-keep-awake@13.0.2:
|
expo-keep-awake@13.0.2:
|
||||||
resolution: {integrity: sha512-kKiwkVg/bY0AJ5q1Pxnm/GvpeB6hbNJhcFsoOWDh2NlpibhCLaHL826KHUM+WsnJRbVRxJ+K9vbPRHEMvFpVyw==}
|
resolution: {integrity: sha512-kKiwkVg/bY0AJ5q1Pxnm/GvpeB6hbNJhcFsoOWDh2NlpibhCLaHL826KHUM+WsnJRbVRxJ+K9vbPRHEMvFpVyw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -2345,6 +2361,11 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
expo: '*'
|
expo: '*'
|
||||||
|
|
||||||
|
expo-permissions@14.4.0:
|
||||||
|
resolution: {integrity: sha512-oAcnJ7dlZhpBydK73cwomA2xofizayVUz+FW5REl7dMu7MYyeN/3aqhlpZ3mYddrxvG161bqu97MQr01UixUnw==}
|
||||||
|
peerDependencies:
|
||||||
|
expo: '*'
|
||||||
|
|
||||||
expo-router@3.5.23:
|
expo-router@3.5.23:
|
||||||
resolution: {integrity: sha512-Re2kYcxov67hWrcjuu0+3ovsLxYn79PuX6hgtYN20MgigY5ttX79KOIBEVGTO3F3y9dxSrGHyy5Z14BcO+usGQ==}
|
resolution: {integrity: sha512-Re2kYcxov67hWrcjuu0+3ovsLxYn79PuX6hgtYN20MgigY5ttX79KOIBEVGTO3F3y9dxSrGHyy5Z14BcO+usGQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -8033,6 +8054,15 @@ snapshots:
|
|||||||
expo: 51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))
|
expo: 51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))
|
||||||
fontfaceobserver: 2.3.0
|
fontfaceobserver: 2.3.0
|
||||||
|
|
||||||
|
expo-image-loader@4.7.0(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-image-picker@15.0.7(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-image-loader: 4.7.0(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8)))
|
||||||
|
|
||||||
expo-keep-awake@13.0.2(expo@51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))):
|
expo-keep-awake@13.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: 51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))
|
expo: 51.0.38(@babel/core@7.25.8)(@babel/preset-env@7.25.8(@babel/core@7.25.8))
|
||||||
@ -8078,6 +8108,10 @@ snapshots:
|
|||||||
- encoding
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
expo-permissions@14.4.0(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-router@3.5.23(k73ovpznblgccxklktj7qyihii):
|
expo-router@3.5.23(k73ovpznblgccxklktj7qyihii):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@expo/metro-runtime': 3.2.3(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))
|
'@expo/metro-runtime': 3.2.3(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))
|
||||||
|
Loading…
Reference in New Issue
Block a user