Skip to content

Commit a1d189f

Browse files
authored
Merge branch 'main' into store-types-seperately
2 parents cfd1584 + c747b8b commit a1d189f

25 files changed

+1639
-792
lines changed

.github/workflows/main.yml

+9-2
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ jobs:
2323
run: npm ci
2424
working-directory: server/
2525

26-
- name: Set up environment variables
26+
- name: Create subdirectory for service account JSON
2727
run: |
2828
mkdir private_key
29-
echo "${{ secrets.SERVICE_ACCOUNT_SECRET }}" > private_key/private.json
3029
working-directory: server/src
3130

31+
- name: Create service account JSON
32+
id: create-service-account-json
33+
uses: jsdaniell/[email protected]
34+
with:
35+
name: "private.json"
36+
json: ${{ secrets.SERVICE_ACCOUNT_SECRET }}
37+
dir: 'server/src/private_key/'
38+
3239
- name: Compile TypeScript files
3340
run: npx tsc
3441
working-directory: server/

client/assets/transparentSend.png

15.1 KB
Loading

client/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"expo-linear-gradient": "~12.3.0",
2323
"expo-linking": "~5.0.2",
2424
"expo-location": "~16.1.0",
25+
"expo-network": "~5.4.0",
2526
"expo-router": "^2.0.0",
2627
"expo-secure-store": "~12.3.1",
2728
"expo-status-bar": "~1.6.0",
@@ -30,13 +31,14 @@
3031
"react": "18.2.0",
3132
"react-native": "0.72.6",
3233
"react-native-dotenv": "^3.4.9",
34+
"react-native-feather": "^1.1.2",
3335
"react-native-fs": "^2.20.0",
3436
"react-native-safe-area-context": "4.6.3",
3537
"react-native-screens": "~3.22.0",
3638
"react-native-uuid": "^2.0.1",
3739
"react-native-web": "~0.19.6",
3840
"socket.io-client": "^4.7.4",
39-
"expo-network": "~5.4.0"
41+
"react-native-svg": "13.9.0"
4042
},
4143
"devDependencies": {
4244
"@babel/core": "^7.20.0",

client/src/components/Auth/AuthenticationResponse.tsx

+38-32
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import React from "react";
2-
import { StyleSheet, Text, Dimensions, TouchableOpacity} from "react-native";
2+
import { StyleSheet, Text, Dimensions, TouchableOpacity } from "react-native";
33
import { FirebaseError } from "firebase/app";
44
import { User } from "firebase/auth";
55

66
//Type to handle Authentication Responses from firebase
7-
export type AuthenticationResponse = {
8-
user: User | null;
9-
error?: undefined;
10-
} | {
11-
user?: undefined;
12-
error: unknown;
13-
}
7+
export type AuthenticationResponse =
8+
| {
9+
user: User | null;
10+
error?: undefined;
11+
}
12+
| {
13+
user?: undefined;
14+
error: unknown;
15+
};
1416

1517
export class CustomError {
1618
public code: string;
@@ -23,7 +25,10 @@ export class CustomError {
2325
}
2426

2527
//Custom responses
26-
export const inValidEmailResponse = new CustomError("Invalid Email", "Please provide a valid email address")
28+
export const inValidEmailResponse = new CustomError(
29+
"Invalid Email",
30+
"Please provide a valid email address"
31+
);
2732

2833
//Function that decodes the error code
2934
const decodeFirebaseError = (error: FirebaseError) => {
@@ -47,54 +52,56 @@ const decodeFirebaseError = (error: FirebaseError) => {
4752

4853
const decodeCustomError = (error: CustomError) => {
4954
return error.message;
50-
}
55+
};
5156

5257
//Function that handles the response depending on type
53-
function handleResponse(response: AuthenticationResponse) {
54-
if(response?.user) {
58+
const handleResponse = (response: AuthenticationResponse) => {
59+
if (response?.user) {
60+
// If the user is not undefined
5561
return "";
5662
}
5763

58-
console.log(response.error)
59-
60-
if(response.error instanceof FirebaseError) {
64+
if (response.error instanceof FirebaseError) {
65+
// If the error is a firebase error
6166
return decodeFirebaseError(response.error);
6267
}
63-
64-
if(response.error instanceof CustomError) {
68+
// If the error is a custom error
69+
if (response.error instanceof CustomError) {
70+
// If the error is a custom error
6571
return decodeCustomError(response.error);
6672
}
6773

68-
return "Unknown error"
69-
}
74+
return "Unknown error";
75+
};
7076

71-
//Something
77+
// Authentication Message Component Props
7278
interface AuthenticationErrorMessageProps {
7379
response: AuthenticationResponse | undefined;
7480
onPress?: () => void;
7581
}
7682

77-
export const AuthenticationErrorMessage: React.FC<AuthenticationErrorMessageProps> = ({ response, onPress }) => {
78-
if( response === undefined ) {
83+
export const AuthenticationErrorMessage: React.FC<
84+
AuthenticationErrorMessageProps
85+
> = ({ response, onPress }) => {
86+
if (response === undefined) {
7987
return null;
8088
}
8189

82-
const errorMessage = handleResponse(response)
90+
const errorMessage = handleResponse(response);
8391

8492
return (
85-
errorMessage &&
86-
<TouchableOpacity style={styles.error_container} onPressIn={onPress}>
93+
errorMessage && (
94+
<TouchableOpacity style={styles.error_container} onPressIn={onPress}>
8795
<Text style={styles.error_text}>{errorMessage}</Text>
88-
</TouchableOpacity>
96+
</TouchableOpacity>
97+
)
8998
);
90-
}
91-
99+
};
92100

93101
const styles = StyleSheet.create({
94102
error_text: {
95103
color: "white",
96104
fontSize: Dimensions.get("window").height * 0.02,
97-
98105
},
99106
error_container: {
100107
display: "flex",
@@ -105,7 +112,6 @@ const styles = StyleSheet.create({
105112
marginTop: Dimensions.get("window").height * 0.005,
106113
width: Dimensions.get("window").width * 0.9,
107114
borderRadius: 10,
108-
padding: 10
109-
}
115+
padding: 10,
116+
},
110117
});
111-

client/src/components/Auth/LoginScreen.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,23 @@ const LoginScreen = () => {
2727
const [email, setEmail] = React.useState<string>("");
2828
const [password, setPassword] = React.useState<string>("");
2929
const [authResponse, setAuthResponse] = React.useState<AuthenticationResponse>();
30-
const [invalidLogin, invalidateLogin] = React.useState<boolean>(false);
30+
const [invalidLogin, invalidateLogin] = React.useState<boolean>(false); // Possbily change this?
3131

32+
// Sign in function with email and password
3233
const onHandleSubmit = async () => {
34+
Keyboard.dismiss();
3335
setAuthResponse(await appSignIn(email, password));
36+
};
37+
38+
// Listens for the response from the sign in function
39+
useEffect(() => {
3440
if (authResponse?.user) {
3541
router.replace("(home)/chatchannel");
3642
} else if (authResponse?.error) {
3743
console.log(authResponse.error);
3844
invalidateLogin(true);
3945
}
40-
};
46+
}, [authResponse])
4147

4248
useEffect(() => {
4349
setEmail(inputEmail?.toString() || ""); // On load of the page, set the email to the inputEmail if they entered it!
@@ -76,7 +82,10 @@ const LoginScreen = () => {
7682
</KeyboardAvoidingView>
7783

7884
<View style={styles.error_container}>
79-
<AuthenticationErrorMessage response={authResponse} onPress={() => setAuthResponse(undefined)} />
85+
<AuthenticationErrorMessage response={authResponse} onPress={() => {
86+
setAuthResponse(undefined)
87+
invalidateLogin(false)
88+
}} />
8089
</View>
8190

8291
</View>

client/src/components/Chat/ChatScreen.tsx

+9-7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { useSettings } from "../../contexts/SettingsContext";
2424
import { useLocation } from "../../contexts/LocationContext";
2525
import { useUser } from "../../contexts/UserContext"; // imported for when it needs to be used
2626
import { AuthStore } from "../../services/store";
27+
import { ChatScreenFooter } from "../Common/ChatScreenFooter"
2728

2829
const ChatScreen = () => {
2930
const settings = useSettings();
@@ -108,13 +109,13 @@ const ChatScreen = () => {
108109
<MessageChannel messages={messages} />
109110
</View>
110111
<View style={styles.footerContainer}>
111-
<ChatInput
112+
<ChatScreenFooter
112113
value={messageContent}
113114
onChangeText={(text: string) => {
114115
setMessageContent(text);
115116
}}
117+
onSend={onHandleSubmit}
116118
/>
117-
<ChatSendButton onPress={onHandleSubmit} />
118119
</View>
119120
</View>
120121
</KeyboardAvoidingView>
@@ -147,16 +148,17 @@ const styles = StyleSheet.create({
147148

148149
footerContainer: {
149150
width: "95%",
150-
minHeight: Dimensions.get("window").height * 0.1,
151+
151152
maxHeight: Dimensions.get("window").height * 0.15,
152153
display: "flex",
153154
flexDirection: "row",
154155
alignItems: "flex-end",
155156
justifyContent: "space-evenly",
156-
paddingBottom: Dimensions.get("window").height * 0.02,
157-
paddingTop: Dimensions.get("window").height * 0.02,
158-
marginTop: 10,
159-
borderTopWidth: 1,
157+
paddingBottom: Dimensions.get("window").height * 0.003,
158+
paddingTop: Dimensions.get("window").height * 0.004,
159+
marginTop: 0,
160+
borderTopWidth: 0,
161+
borderColor: "#8E8E8E",
160162
},
161163
});
162164

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from 'react'
2+
import { TextInput, View, StyleSheet, Dimensions, Platform, TouchableOpacity } from 'react-native'
3+
import { ChatSendButton } from './CustomButtons'
4+
import { Smile, Image } from "react-native-feather";
5+
6+
interface ChatInputProps {
7+
value?: string,
8+
onChangeText?: (text: string) => void
9+
invalid?: boolean,
10+
onSend?: () => void,
11+
}
12+
13+
export const ChatScreenFooter: React.FC<ChatInputProps> = ({ value, onChangeText, onSend }) => {
14+
15+
16+
17+
return (
18+
<View style={styles.container}>
19+
<View style={styles.iconContainer}>
20+
<TouchableOpacity>
21+
<Image color={"black"} strokeWidth={1.8} style={styles.icons}/>
22+
</TouchableOpacity>
23+
<TouchableOpacity>
24+
<Smile color={"black"} strokeWidth={1.8} style={styles.icons}/>
25+
</TouchableOpacity>
26+
</View>
27+
<TextInput
28+
placeholder='Say Something...'
29+
multiline={true}
30+
value={value}
31+
onChangeText={onChangeText}
32+
maxLength={500}
33+
style={styles.messageInput}/>
34+
<View style={styles.sendButtonContainer}>
35+
<ChatSendButton onPress={(onSend)} />
36+
</View>
37+
</View>
38+
)
39+
};
40+
41+
const styles = StyleSheet.create({
42+
43+
container: {
44+
flexDirection: 'row',
45+
flex: 1,
46+
alignItems: 'center',
47+
borderColor: "#8E8E8E",
48+
borderWidth: 1,
49+
borderRadius: Dimensions.get('window').width * 0.058,
50+
marginHorizontal: Dimensions.get('window').width * 0.005,
51+
marginBottom: Platform.OS === 'ios' ? 0 : 5,
52+
minHeight: Dimensions.get('window').width * 0.113,
53+
maxHeight: Dimensions.get('window').width * 0.3,
54+
},
55+
messageInput: {
56+
fontSize: 16,
57+
flex: 1,
58+
marginBottom: Platform.OS === 'ios' ? 5 : 4,
59+
marginTop: Platform.OS === 'ios' ? 2 : 4,
60+
marginHorizontal: Dimensions.get('window').width * 0.018,
61+
62+
63+
},
64+
icons: {
65+
marginHorizontal: Dimensions.get('window').width * 0.008,
66+
},
67+
iconContainer: {
68+
marginLeft: Dimensions.get('window').width * 0.02,
69+
marginBottom: Dimensions.get('window').width * 0.025,
70+
marginTop: Dimensions.get('window').width * 0.025,
71+
flexDirection: 'row',
72+
alignItems: "flex-end",
73+
justifyContent: "flex-end",
74+
alignSelf: "stretch",
75+
76+
77+
},
78+
sendButtonContainer: {
79+
alignItems: "flex-end",
80+
justifyContent: "flex-end",
81+
flexDirection: "row",
82+
alignSelf: "stretch",
83+
marginRight: Dimensions.get('window').width * 0.01,
84+
marginBottom: Dimensions.get('window').width * 0.01,
85+
marginTop: Dimensions.get('window').width * 0.01,
86+
}
87+
88+
});

client/src/components/Common/CustomButtons.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,26 @@ import { ChatSendButtonProps } from '../../types/Props';
55
export const ChatSendButton: React.FC<ChatSendButtonProps> = ({ onPress }) => {
66
return (
77
<TouchableOpacity style={styles.sendButton} onPress={onPress}>
8-
<Image style={styles.sendButtonImage} source={require('../../../assets/send.png')}/>
8+
<Image style={styles.sendButtonImage} source={require('../../../assets/transparentSend.png')}/>
99
</TouchableOpacity>
1010
)
1111
}
1212

1313
const styles = StyleSheet.create({
1414
sendButton: {
15-
height: Dimensions.get('window').height * 0.055,
16-
width: Dimensions.get('window').height * 0.055,
17-
borderRadius: 30,
18-
backgroundColor: 'blue',
15+
height: Dimensions.get('window').width * 0.09,
16+
width: Dimensions.get('window').width * 0.09,
17+
borderRadius: 100,
18+
backgroundColor: '#34D1BF',
1919
justifyContent: 'center',
2020
alignItems: 'center',
2121
},
2222

2323
sendButtonImage:{
24-
height: Dimensions.get('window').height * 0.033,
25-
width: Dimensions.get('window').height * 0.033,
26-
marginLeft: Dimensions.get('window').width * 0.01,
24+
height: "64%",
25+
width: "64%",
26+
marginLeft: "13%",
27+
tintColor: 'white',
2728
},
2829
})
2930

0 commit comments

Comments
 (0)