Commit b50bc385 authored by Malsha Rathnasiri's avatar Malsha Rathnasiri

Merge branch 'IT18094664'

parents 816c46f3 7cfb27ff
venv/
backend/output.wav
backend/backend/output.m4a
ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffmpeg.exe
ngrok.exe
ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffplay.exe
ffmpeg-2022-08-03-git-d3f48e68b3-essentials_build/ffprobe.exe
{
"e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true,
"af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true,
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true,
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true
}
node_modules/
node_modules2/
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
# macOS
.DS_Store
import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import useCachedResources from './hooks/useCachedResources';
import useColorScheme from './hooks/useColorScheme';
import Navigation from './navigation/index';
import { NativeBaseProvider, Box } from "native-base";
export default function App() {
const isLoadingComplete = useCachedResources();
const colorScheme = useColorScheme();
if (!isLoadingComplete) {
return null;
} else {
return (
<NativeBaseProvider>
<SafeAreaProvider>
<Navigation colorScheme={colorScheme} />
<StatusBar />
</SafeAreaProvider>
</NativeBaseProvider>
);
}
}
import React, { createContext, useContext, useState, useEffect, useLayoutEffect } from "react";
import axios from "axios";
import { BACKEND_URL } from "./constants";
// import { nexlAxios } from "../../constants/helper";
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Platform } from 'react-native'
// import {
// IAuthContext,
// IAuthRequest,
// STORAGE_BEARER_TOKEN,
// UNINITIALISED,
// USER_EMAIL,
// } from "./IAuthContext";
// import { Loading } from "./state/Loading";
// import { getEnvironment } from "../../constants/variables";
// import { AxiosError, AxiosResponse } from "axios";
// import { rollbar } from "./ErrorBoundary";
// import { ENDPOINT as endpoint } from "./constants";
// const AuthContext = createContext({
// isLoggedIn: false,
// token: "",
// email: "",
// error: "",
// loading: false,
// initialised: false,
// login: UNINITIALISED,
// logout: UNINITIALISED,
// });
// export const useAuthContext = () => useContext(AuthContext);
// export const AuthConsumer = AuthContext.Consumer;
// interface IProps {
// children: any;
// }
// interface ILoginData {
// error: string;
// user: {
// email: string;
// id: string;
// first_name: string;
// last_name: string;
// };
// }
// const endpoint = getEnvironment().endpoint;
export const isLoggedIn = async () => {
const token = await AsyncStorage.getItem('access_token')
console.log({ token, has: !!token })
return !!token
}
export const login = async (username, password) => {
const endpoint = false ? 'register' : 'login';
const payload = { username: username, password: password }
const headers = new Headers({ "Content-Type": 'application./json', 'mode': 'no-cors', 'Access-Control-Allow-Headers': '*' })
const options = { method: 'POST', data: payload, headers }
axios.defaults.baseURL = BACKEND_URL;
axios.defaults.timeout = 1500;
console.log({ payload })
return axios.post('/api/auth/token/obtain/', payload)
.then(async (response) => {
const { access, refresh, user } = response.data;
axios.defaults.headers.common.Authorization = `Token ${access}`;
await AsyncStorage.setItem('user_id', String(user.id))
await AsyncStorage.setItem('username', user.username)
await AsyncStorage.setItem('user_email', user.email)
await AsyncStorage.setItem('access_token', access)
await AsyncStorage.setItem('refresh_token', refresh)
console.log("login successful")
return true
// Actions.main();
})
.catch(error => {
console.log('error in login authentication')
throw Error(error)
});
}
export const logout = async () => {
await AsyncStorage.clear()
}
// export const AuthProvider = ({ children }) => {
// const [isLoggedIn, setIsLoggedIn] = useState(false);
// const [token, setToken] = useState("");
// const [email, setEmail] = useState("");
// const [error, setError] = useState("");
// const [loading, setLoading] = useState(false);
// const [initialised, setInitialised] = useState(false);
// const login = async ({ email, password, rememberMe }) => {
// setLoading(true);
// nexlAxios(false)
// .post(`${endpoint}/accounts/sign_in.json`, {
// source: "iOS app",
// account: {
// email,
// password,
// remember_me: rememberMe ? "1" : "0",
// },
// })
// .then(async (response) => {
// setLoading(false);
// const user = response.data.user;
// user.email && setIsLoggedIn(true);
// const token = response.headers["authorization"];
// setToken(token);
// await AsyncStorage.setItem(USER_EMAIL, email);
// setEmail(email);
// rollbar.setPerson(user.id, `${user.first_name} ${user.last_name}`, user.email);
// })
// .catch((result) => {
// setLoading(false);
// setError(
// result?.response?.data?.error || result?.message || "An unknown error has occurred.",
// );
// });
// };
// const loginWithBearerToken = async (bearer) => {
// if (bearer) {
// setLoading(true);
// await nexlAxios(false, bearer)
// .post(`${endpoint}/accounts/sign_in.json`, undefined, {
// headers: {
// Authorization: bearer,
// },
// })
// .then((response) => {
// setLoading(false);
// const user = response.data.user;
// user.email && setIsLoggedIn(true);
// rollbar.setPerson(user.id, `${user.first_name} ${user.last_name}`, user.email);
// })
// .catch(() => {
// setLoading(false);
// setToken("");
// });
// }
// };
// const logout = async () => {
// const token = await AsyncStorage.getItem(STORAGE_BEARER_TOKEN);
// token && (await nexlAxios(false, token).post(`${endpoint}/sign_out.json`));
// setToken("");
// setIsLoggedIn(false);
// await AsyncStorage.removeItem(STORAGE_BEARER_TOKEN);
// rollbar.clearPerson();
// };
// // look if token / email exist in local storage on initialising the app
// // if token exists, try log in with token
// useLayoutEffect(() => {
// let isMounted = true;
// const initialise = async () => {
// const bearerToken = await AsyncStorage.getItem(STORAGE_BEARER_TOKEN);
// setToken(bearerToken || "");
// const userEmail = await AsyncStorage.getItem(USER_EMAIL);
// setEmail(userEmail || "");
// bearerToken && (await loginWithBearerToken(bearerToken));
// setInitialised(true);
// };
// if (isMounted) {
// initialise();
// }
// return () => {
// isMounted = false;
// };
// }, []);
// // update token to local storage on token change
// useEffect(() => {
// AsyncStorage.setItem(STORAGE_BEARER_TOKEN, token);
// }, [token]);
// return (
// <AuthContext.Provider
// value={{
// login,
// isLoggedIn,
// logout,
// token,
// email: email.toLowerCase(),
// loading,
// error,
// initialised,
// }}
// >
// {initialised ? children : <Loading copy="Logging in..." />}
// </AuthContext.Provider>
// );
// };
\ No newline at end of file
import { BACKEND_URL } from "./constants"
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from "@react-navigation/native";
import axios from "axios";
//"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjYxMzU2NDA5LCJpYXQiOjE2NjAxNDY4MDksImp0aSI6ImFhMTljMmY2ZDNkMzRiNDdhZmZmM2FjMzVjNzI4MWJhIiwidXNlcl9pZCI6MX0.IVzibo_Rf2xzoT1J5o1L3zwu3mco6ODcNPC-7imu3Lo"
// const headers =
const getHeaders = async () => {
var token = await AsyncStorage.getItem('access_token')
return {
Authorization: `JWT ${token}`, 'Content-Type': 'application/json',
// "Access-Control-Allow-Methods": "DELETE, POST, GET, OPTIONS",
// "Access-Control-Allow-Headers": "Content-Type, Authorization, Access-Control-Allow-Methods",
// "Access-Control-Allow-Origin": "*",
}
}
export const create = async (resource, values) => {
const headers = await getHeaders()
console.log({ headers }, 'create')
console.log({values})
try {
return fetch(`${BACKEND_URL}/${resource}/`, { method: 'POST', body: JSON.stringify(values), headers })
// return Axios.post(`${BACKEND_URL}/${resource}/`, values)
}
catch (e) {
console.log(e)
}
}
export const getList = async (resource, params) => {
const url = new URL(`${BACKEND_URL}/${resource}/`)
if (params) {
Object.keys(params).map(key => {
url.searchParams.append(key, params[key])
})
}
const headers = await getHeaders()
console.log(headers, 'getList')
return fetch(url, { method: 'GET', headers: headers })
return axios.get(url.toString(), null, { headers })
}
export const getOne = async (resource, id) => {
const url = new URL(`${BACKEND_URL}/${resource}/${id}/`)
const headers = await getHeaders()
console.log(headers, 'getONe')
return fetch(url, { method: "GET", headers: headers })
}
\ No newline at end of file
// export const BACKEND_URL = "http://192.168.8.103:8000"
import { Platform } from 'react-native'
export const BACKEND_ADDRESS = Platform.OS == 'web' ? "http://127.0.0.1:8000" : "https://c881-2402-4000-2280-1401-f8b7-3e41-83a-2250.in.ngrok.io"
export const BACKEND_URL = `${BACKEND_ADDRESS}`
{
"expo": {
"name": "MobileApp",
"slug": "MobileApp",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "myapp",
"userInterfaceStyle": "automatic",
"splash": {
"image": "./assets/images/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"favicon": "./assets/images/favicon.png"
}
}
}
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo']
};
};
import React from 'react'
import { Text, View, StyleSheet, Button } from 'react-native';
import { Audio } from 'expo-av';
import { createIconSetFromFontello } from '@expo/vector-icons';
import * as FileSystem from 'expo-file-system';
import { BACKEND_URL } from '../api/constants';
export const AudioRecorder = ({ setDetectedText }) => {
const [recording, setRecording] = React.useState();
const [sound, setSound] = React.useState();
async function startRecording() {
try {
console.log('Requesting permissions..');
await Audio.requestPermissionsAsync();
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
console.log('Starting recording..');
const { recording } = await Audio.Recording.createAsync(
Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
);
setRecording(recording);
console.log('Recording started');
} catch (err) {
console.error('Failed to start recording', err);
}
}
async function stopRecording() {
console.log('Stopping recording..');
setRecording(undefined);
await recording.stopAndUnloadAsync();
const uri = recording.getURI();
console.log('Recording stopped and stored at', uri)
//console.log(recording)
const headers = {
'Content-Type': 'multipart/form-data'
// 'Content-Type': 'application/x-www-form-urlencoded',
}
playSound(uri)
FileSystem.uploadAsync(`${BACKEND_URL}/mlmodels/detect/`, uri, { headers: headers, uploadType: FileSystem.FileSystemUploadType.MULTIPART })
.then(data => JSON.parse(data.body))
.then(data => {
// console.log({ result: data });
setDetectedText(data.result);
// setTimeout(() => setDetectedText(''), 1000)
})
.catch(err => console.log({ err }))
}
async function playSound(uri) {
console.log('Loading Sound');
// const { sound } = await Audio.Sound.createAsync(
// require(uri)
// );
// setSound(sound);
// console.log('Playing Sound');
// await sound.playAsync();
}
return (
<Button
style={{ height: '100%', padding: 5 }}
title={recording ? 'Stop' : 'Record'}
onPress={recording ? stopRecording : startRecording}
/>
);
}
\ No newline at end of file
import * as WebBrowser from 'expo-web-browser';
import { StyleSheet, TouchableOpacity } from 'react-native';
import Colors from '../constants/Colors';
import { MonoText } from './StyledText';
import { Text, View } from './Themed';
export default function EditScreenInfo({ path }: { path: string }) {
return (
<View>
<View style={styles.getStartedContainer}>
<Text
style={styles.getStartedText}
lightColor="rgba(0,0,0,0.8)"
darkColor="rgba(255,255,255,0.8)">
Open up the code for this screen:
</Text>
<View
style={[styles.codeHighlightContainer, styles.homeScreenFilename]}
darkColor="rgba(255,255,255,0.05)"
lightColor="rgba(0,0,0,0.05)">
<MonoText>{path}</MonoText>
</View>
<Text
style={styles.getStartedText}
lightColor="rgba(0,0,0,0.8)"
darkColor="rgba(255,255,255,0.8)">
Change any of the text, save the file, and your app will automatically update.
</Text>
</View>
<View style={styles.helpContainer}>
<TouchableOpacity onPress={handleHelpPress} style={styles.helpLink}>
<Text style={styles.helpLinkText} lightColor={Colors.light.tint}>
Tap here if your app doesn't automatically update after making changes
</Text>
</TouchableOpacity>
</View>
</View>
);
}
function handleHelpPress() {
WebBrowser.openBrowserAsync(
'https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet'
);
}
const styles = StyleSheet.create({
getStartedContainer: {
alignItems: 'center',
marginHorizontal: 50,
},
homeScreenFilename: {
marginVertical: 7,
},
codeHighlightContainer: {
borderRadius: 3,
paddingHorizontal: 4,
},
getStartedText: {
fontSize: 17,
lineHeight: 24,
textAlign: 'center',
},
helpContainer: {
marginTop: 15,
marginHorizontal: 20,
alignItems: 'center',
},
helpLink: {
paddingVertical: 15,
},
helpLinkText: {
textAlign: 'center',
},
});
import { Ionicons } from "@expo/vector-icons";
import React, { useState } from "react";
import { View } from "react-native";
import { CONVO_DEFAULT_ICON_COLOR, CONVO_STOP_ICON_COLOR, styles } from "../util/styles";
import * as Speech from 'expo-speech';
export const PlayMessage = ({ message }) => {
const [isPlaying, setIsPlaying] = useState(false)
const [isTtsReady, setIsTtsReady] = useState(false)
// // Tts.setDucking(true);
// Tts.addEventListener('tts-start', (event) => console.log("start"));
// Tts.addEventListener('tts-finish', (event) => console.log("finish"));
// const synth = window.speechSynthesis;
// const speech = new SpeechSynthesisUtterance(message)
// speech.lang = 'en'
// speech.onend((e) => console.log('end'))
const onSpeechDone = (props) => {
setIsPlaying(false)
}
const onPlayPress = () => {
setIsPlaying(true)
// synth.speak(speech)
Speech.speak(message, { onDone: onSpeechDone });
// speech.onend((e) => console.log('end'))
}
const onStopPress = () => {
Speech.stop()
setIsPlaying(false)
}
if (!isPlaying) {
return (
<Ionicons name="play" size={15} style={styles.chatIcon} onPress={onPlayPress} color={CONVO_DEFAULT_ICON_COLOR} />
)
}
else {
return (
<Ionicons name="stop" size={15} style={styles.chatIcon} onPress={onStopPress} color={CONVO_STOP_ICON_COLOR} />
)
}
}
\ No newline at end of file
import { Text, TextProps } from './Themed';
export function MonoText(props: TextProps) {
return <Text {...props} style={[props.style, { fontFamily: 'space-mono' }]} />;
}
/**
* Learn more about Light and Dark modes:
* https://docs.expo.io/guides/color-schemes/
*/
import { Text as DefaultText, View as DefaultView } from 'react-native';
import Colors from '../constants/Colors';
import useColorScheme from '../hooks/useColorScheme';
export function useThemeColor(
props: { light?: string; dark?: string },
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
) {
const theme = useColorScheme();
const colorFromProps = props[theme];
if (colorFromProps) {
return colorFromProps;
} else {
return Colors[theme][colorName];
}
}
type ThemeProps = {
lightColor?: string;
darkColor?: string;
};
export type TextProps = ThemeProps & DefaultText['props'];
export type ViewProps = ThemeProps & DefaultView['props'];
export function Text(props: TextProps) {
const { style, lightColor, darkColor, ...otherProps } = props;
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
return <DefaultText style={[{ color }, style]} {...otherProps} />;
}
export function View(props: ViewProps) {
const { style, lightColor, darkColor, ...otherProps } = props;
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
}
import React, { useEffect, useState } from 'react'
import { View, Text, ActivityIndicator } from 'react-native'
import AsyncStorage from '@react-native-async-storage/async-storage'
export const UserProfile = () => {
const [loading, setLoading] = useState(true)
const [username, setUsername] = useState("")
const [modalVisible, setModalVisible] = useState(false)
useEffect(() => {
AsyncStorage.getItem('username').then((username) => {
setUsername(username)
setLoading(false)
})
})
if (loading) {
return <ActivityIndicator />
}
return (
<>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
setModalVisible(!modalVisible);
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Hello World!</Text>
<Pressable
style={[styles.button, styles.buttonClose]}
onPress={() => setModalVisible(!modalVisible)}>
<Text style={styles.textStyle}>Hide Modal</Text>
</Pressable>
</View>
</View>
</Modal>
</>
)
}
\ No newline at end of file
import * as React from 'react';
import renderer from 'react-test-renderer';
import { MonoText } from '../StyledText';
it(`renders correctly`, () => {