Almost done with rewrite

This commit is contained in:
Gabriel Brown 2024-10-15 16:58:01 -05:00
parent 5549cbbe10
commit 701315011b
10 changed files with 277 additions and 14 deletions

View 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)',
},
});

View 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',
},
})

View File

View File

View File

View File

View 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);
};

View File

@ -1,26 +1,27 @@
/**
* Below are the colors that are used in the app. The colors are defined in the light and dark mode.
* 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';
// Dark mode colors
const dark = '#2e2f3d';
const tintColorDark = '#fff';
const iconColorDark = '#9BA1A6';
// Light mode colors
const light = '#ECEDEE';
const tintColorLight = '#0a7ea4';
const iconColorLight = '#687076';
export const Colors = {
light: {
text: '#11181C',
background: '#fff',
text: dark,
background: light,
tint: tintColorLight,
icon: '#687076',
tabIconDefault: '#687076',
icon: iconColorLight,
tabIconDefault: iconColorLight,
tabIconSelected: tintColorLight,
},
dark: {
text: '#ECEDEE',
background: '#151718',
text: dark,
background: light,
tint: tintColorDark,
icon: '#9BA1A6',
tabIconDefault: '#9BA1A6',
icon: iconColorDark,
tabIconDefault: iconColorDark,
tabIconSelected: tintColorDark,
},
};

View File

@ -21,9 +21,11 @@
"expo-constants": "~16.0.2",
"expo-device": "~6.0.2",
"expo-font": "~12.0.9",
"expo-image-picker": "~15.0.7",
"expo-linking": "~6.3.1",
"expo-location": "~17.0.1",
"expo-notifications": "~0.28.18",
"expo-permissions": "^14.4.0",
"expo-router": "~3.5.23",
"expo-secure-store": "~13.0.2",
"expo-splash-screen": "~0.27.5",

34
pnpm-lock.yaml generated
View File

@ -29,6 +29,9 @@ importers:
expo-font:
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)))
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:
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)))
@ -38,6 +41,9 @@ importers:
expo-notifications:
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)))
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:
specifier: ~3.5.23
version: 3.5.23(k73ovpznblgccxklktj7qyihii)
@ -2320,6 +2326,16 @@ packages:
peerDependencies:
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:
resolution: {integrity: sha512-kKiwkVg/bY0AJ5q1Pxnm/GvpeB6hbNJhcFsoOWDh2NlpibhCLaHL826KHUM+WsnJRbVRxJ+K9vbPRHEMvFpVyw==}
peerDependencies:
@ -2345,6 +2361,11 @@ packages:
peerDependencies:
expo: '*'
expo-permissions@14.4.0:
resolution: {integrity: sha512-oAcnJ7dlZhpBydK73cwomA2xofizayVUz+FW5REl7dMu7MYyeN/3aqhlpZ3mYddrxvG161bqu97MQr01UixUnw==}
peerDependencies:
expo: '*'
expo-router@3.5.23:
resolution: {integrity: sha512-Re2kYcxov67hWrcjuu0+3ovsLxYn79PuX6hgtYN20MgigY5ttX79KOIBEVGTO3F3y9dxSrGHyy5Z14BcO+usGQ==}
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))
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))):
dependencies:
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
- 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):
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))