├── assets ├── images │ ├── icon.png │ ├── chatbg.png │ ├── favicon.png │ ├── splash.png │ ├── user-icon.png │ ├── icon-square.png │ ├── welcome-img.png │ └── adaptive-icon.png └── fonts │ └── SpaceMono-Regular.ttf ├── tsconfig.json ├── babel.config.js ├── .gitignore ├── components ├── StyledText.tsx ├── __tests__ │ └── StyledText-test.js ├── floatingButton │ ├── style.ts │ └── index.tsx ├── chatMessage │ ├── style.ts │ └── index.tsx ├── inputBox │ ├── style.ts │ └── index.tsx ├── EditScreenInfo.tsx ├── chatList │ ├── style.ts │ └── index.tsx └── Themed.tsx ├── screens ├── ContactScreen.tsx ├── CallScreen.tsx ├── StatusScreen.tsx ├── CameraScreen.tsx ├── ChatScreen.tsx ├── ChatRoomScreen.tsx ├── NotFoundScreen.tsx └── ModalScreen.tsx ├── constants ├── Layout.ts ├── Colors.ts └── data │ ├── Users.ts │ ├── Chats.ts │ └── ChatRooms.ts ├── .expo-shared └── assets.json ├── hooks ├── useColorScheme.ts └── useCachedResources.ts ├── App.tsx ├── app.json ├── navigation ├── LinkingConfiguration.ts └── index.tsx ├── types.tsx └── package.json /assets/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/icon.png -------------------------------------------------------------------------------- /assets/images/chatbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/chatbg.png -------------------------------------------------------------------------------- /assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/favicon.png -------------------------------------------------------------------------------- /assets/images/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/splash.png -------------------------------------------------------------------------------- /assets/images/user-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/user-icon.png -------------------------------------------------------------------------------- /assets/images/icon-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/icon-square.png -------------------------------------------------------------------------------- /assets/images/welcome-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/welcome-img.png -------------------------------------------------------------------------------- /assets/images/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/images/adaptive-icon.png -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jadoiconic/whatsAppNew/HEAD/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache(true); 3 | return { 4 | presets: ['babel-preset-expo'] 5 | }; 6 | }; 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .expo/ 3 | dist/ 4 | npm-debug.* 5 | *.jks 6 | *.p8 7 | *.p12 8 | *.key 9 | *.mobileprovision 10 | *.orig.* 11 | web-build/ 12 | 13 | # macOS 14 | .DS_Store 15 | -------------------------------------------------------------------------------- /components/StyledText.tsx: -------------------------------------------------------------------------------- 1 | import { Text, TextProps } from './Themed'; 2 | 3 | export function MonoText(props: TextProps) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /screens/ContactScreen.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from 'react-native' 2 | import React from 'react' 3 | 4 | const ContactScreen = () => { 5 | return ( 6 | 7 | ContactScreen 8 | 9 | ) 10 | } 11 | 12 | export default ContactScreen -------------------------------------------------------------------------------- /constants/Layout.ts: -------------------------------------------------------------------------------- 1 | import { Dimensions } from 'react-native'; 2 | 3 | const width = Dimensions.get('window').width; 4 | const height = Dimensions.get('window').height; 5 | 6 | export default { 7 | window: { 8 | width, 9 | height, 10 | }, 11 | isSmallDevice: width < 375, 12 | }; 13 | -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "e997a5256149a4b76e6bfd6cbf519c5e5a0f1d278a3d8fa1253022b03c90473b": true, 3 | "af683c96e0ffd2cf81287651c9433fa44debc1220ca7cb431fe482747f34a505": true, 4 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 5 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 6 | } 7 | -------------------------------------------------------------------------------- /components/__tests__/StyledText-test.js: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | 4 | import { MonoText } from '../StyledText'; 5 | 6 | it(`renders correctly`, () => { 7 | const tree = renderer.create(Snapshot test!).toJSON(); 8 | 9 | expect(tree).toMatchSnapshot(); 10 | }); 11 | -------------------------------------------------------------------------------- /screens/CallScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import { Text, View } from '../components/Themed'; 4 | 5 | export default function CallScreen() { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | const styles = StyleSheet.create({ 14 | container: { 15 | flex: 1, 16 | alignItems: 'center', 17 | justifyContent: 'center', 18 | }, 19 | }); 20 | -------------------------------------------------------------------------------- /hooks/useColorScheme.ts: -------------------------------------------------------------------------------- 1 | import { ColorSchemeName, useColorScheme as _useColorScheme } from 'react-native'; 2 | 3 | // The useColorScheme value is always either light or dark, but the built-in 4 | // type suggests that it can be null. This will not happen in practice, so this 5 | // makes it a bit easier to work with. 6 | export default function useColorScheme(): NonNullable { 7 | return _useColorScheme() as NonNullable; 8 | } 9 | -------------------------------------------------------------------------------- /constants/Colors.ts: -------------------------------------------------------------------------------- 1 | const tintColorLight = '#075E54'; 2 | const tintColorDark = '#fff'; 3 | 4 | export default { 5 | light: { 6 | text: '#000', 7 | background: '#fff', 8 | tint: tintColorLight, 9 | tabIconDefault: '#ccc', 10 | tabIconSelected: tintColorLight, 11 | }, 12 | dark: { 13 | text: '#fff', 14 | background: '#000', 15 | tint: tintColorDark, 16 | tabIconDefault: '#ccc', 17 | tabIconSelected: tintColorDark, 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /screens/StatusScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import EditScreenInfo from '../components/EditScreenInfo'; 4 | import { Text, View } from '../components/Themed'; 5 | 6 | export default function StatusScreen() { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | } 13 | 14 | const styles = StyleSheet.create({ 15 | container: { 16 | flex: 1, 17 | alignItems: 'center', 18 | justifyContent: 'center', 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /components/floatingButton/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import Colors from '../../constants/Colors'; 3 | 4 | 5 | const styles = StyleSheet.create({ 6 | container:{ 7 | backgroundColor:Colors.light.tint, 8 | width:50, 9 | height:50, 10 | borderRadius:100, 11 | justifyContent:'center', 12 | alignItems:'center', 13 | marginRight:10, 14 | position:'absolute', 15 | bottom:20, 16 | right:10, 17 | }, 18 | }) 19 | 20 | export default styles 21 | -------------------------------------------------------------------------------- /components/chatMessage/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import Colors from '../../constants/Colors'; 3 | 4 | 5 | const styles = StyleSheet.create({ 6 | container:{ 7 | padding:10, 8 | }, 9 | user:{ 10 | color: Colors.light.tint, 11 | fontWeight: 'bold' 12 | }, 13 | message:{ 14 | marginVertical:4, 15 | }, 16 | time:{ 17 | alignSelf: 'flex-end', 18 | color:'grey' 19 | }, 20 | messageBox:{ 21 | borderRadius:5, 22 | padding:10, 23 | }, 24 | }) 25 | 26 | export default styles; -------------------------------------------------------------------------------- /screens/CameraScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | import EditScreenInfo from '../components/EditScreenInfo'; 4 | import { Text, View } from '../components/Themed'; 5 | import { RootTabScreenProps } from '../types'; 6 | 7 | export default function CameraScreen({ navigation }: RootTabScreenProps<'Camera'>) { 8 | return ( 9 | 10 | 11 | 12 | ); 13 | } 14 | 15 | const styles = StyleSheet.create({ 16 | container: { 17 | flex: 1, 18 | alignItems: 'center', 19 | justifyContent: 'center', 20 | }, 21 | }); 22 | -------------------------------------------------------------------------------- /App.tsx: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar'; 2 | import { SafeAreaProvider } from 'react-native-safe-area-context'; 3 | 4 | import useCachedResources from './hooks/useCachedResources'; 5 | import useColorScheme from './hooks/useColorScheme'; 6 | import Navigation from './navigation'; 7 | 8 | export default function App() { 9 | const isLoadingComplete = useCachedResources(); 10 | const colorScheme = useColorScheme(); 11 | 12 | if (!isLoadingComplete) { 13 | return null; 14 | } else { 15 | return ( 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /screens/ChatScreen.tsx: -------------------------------------------------------------------------------- 1 | import { FlatList, StyleSheet,TouchableOpacity } from 'react-native'; 2 | import ChatListItem from '../components/chatList'; 3 | 4 | import { Text, View } from '../components/Themed'; 5 | import { RootTabScreenProps } from '../types'; 6 | import ChatRooms from '../constants/data/ChatRooms'; 7 | import FloatButton from '../components/floatingButton'; 8 | 9 | export default function ChatScreen({ navigation }: RootTabScreenProps<'Chats'>) { 10 | return ( 11 | 12 | } 15 | keyExtractor={(item)=> item.id} 16 | /> 17 | 18 | 19 | 20 | ); 21 | } 22 | 23 | const styles = StyleSheet.create({ 24 | container: { 25 | flex: 1, 26 | }, 27 | }); 28 | -------------------------------------------------------------------------------- /components/floatingButton/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text,TouchableOpacity } from 'react-native' 2 | import React from 'react' 3 | import { MaterialCommunityIcons } from '@expo/vector-icons' 4 | import styles from './style' 5 | import { useNavigation } from '@react-navigation/native' 6 | 7 | const FloatButton = () => { 8 | 9 | const navigation = useNavigation() 10 | const oneNewChat = ()=>{ 11 | navigation.navigate('Contact') 12 | } 13 | return ( 14 | 15 | 16 | 17 | 23 | 24 | 25 | 26 | ) 27 | } 28 | 29 | export default FloatButton -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "WhatsAppNew", 4 | "slug": "WhatsAppNew", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/images/icon.png", 8 | "scheme": "myapp", 9 | "userInterfaceStyle": "automatic", 10 | "splash": { 11 | "image": "./assets/images/splash.png", 12 | "resizeMode": "contain", 13 | "backgroundColor": "#ffffff" 14 | }, 15 | "updates": { 16 | "fallbackToCacheTimeout": 0 17 | }, 18 | "assetBundlePatterns": [ 19 | "**/*" 20 | ], 21 | "ios": { 22 | "supportsTablet": true 23 | }, 24 | "android": { 25 | "adaptiveIcon": { 26 | "foregroundImage": "./assets/images/adaptive-icon.png", 27 | "backgroundColor": "#ffffff" 28 | } 29 | }, 30 | "web": { 31 | "favicon": "./assets/images/favicon.png" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /components/inputBox/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import Colors from '../../constants/Colors'; 3 | 4 | 5 | const styles = StyleSheet.create({ 6 | container:{ 7 | flexDirection:'row', 8 | margin:10, 9 | alignItems:'flex-end', 10 | }, 11 | btn:{ 12 | backgroundColor:'#128755', 13 | borderRadius:100, 14 | padding:10, 15 | }, 16 | input:{ 17 | flex:1, 18 | minHeight:40, 19 | maxHeight:60, 20 | marginHorizontal:10, 21 | }, 22 | icon:{ 23 | marginHorizontal:3, 24 | }, 25 | mainContainer:{ 26 | flexDirection:'row', 27 | backgroundColor:'white', 28 | padding:5, 29 | alignItems:'center', 30 | borderRadius:30, 31 | marginRight:5, 32 | marginBottom:5, 33 | flex:1, 34 | 35 | } 36 | }) 37 | 38 | export default styles -------------------------------------------------------------------------------- /screens/ChatRoomScreen.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, FlatList,ImageBackground } from 'react-native' 2 | import React from 'react' 3 | import { useRoute } from '@react-navigation/native' 4 | import ChatMessage from '../components/chatMessage' 5 | import ChatRoomsData from '../constants/data/Chats' 6 | import InputComp from '../components/inputBox' 7 | 8 | const ChatRoomScreen = () => { 9 | const route = useRoute() 10 | // console.warn(route.params) 11 | return ( 12 | 17 | ()} 20 | inverted 21 | /> 22 | 23 | 24 | ) 25 | } 26 | 27 | export default ChatRoomScreen -------------------------------------------------------------------------------- /components/EditScreenInfo.tsx: -------------------------------------------------------------------------------- 1 | import * as WebBrowser from 'expo-web-browser'; 2 | import { StyleSheet, TouchableOpacity } from 'react-native'; 3 | 4 | import Colors from '../constants/Colors'; 5 | import { MonoText } from './StyledText'; 6 | import { Text, View } from './Themed'; 7 | 8 | export default function EditScreenInfo() { 9 | return ( 10 | 11 | 12 | 13 | Welcome Back 14 | 15 | 16 | 17 | ); 18 | } 19 | 20 | function handleHelpPress() { 21 | alert("Cliked"); 22 | } 23 | 24 | const styles = StyleSheet.create({ 25 | 26 | helpContainer: { 27 | marginTop: 15, 28 | marginHorizontal: 20, 29 | alignItems: 'center', 30 | }, 31 | helpLink: { 32 | paddingVertical: 15, 33 | }, 34 | }); 35 | -------------------------------------------------------------------------------- /components/chatList/style.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from "react-native"; 2 | 3 | const styles = StyleSheet.create({ 4 | container:{ 5 | flexDirection:'row', 6 | width:'100%', 7 | justifyContent:'space-between', 8 | padding:10, 9 | }, 10 | leftContainer:{ 11 | flexDirection:'row', 12 | }, 13 | avatar:{ 14 | width:60, 15 | height:60, 16 | marginRight:10, 17 | borderRadius:100, 18 | }, 19 | username:{ 20 | fontWeight:'bold', 21 | }, 22 | lastMessage:{ 23 | fontSize:16, 24 | color:'grey', 25 | maxWidth:220, 26 | // backgroundColor:'#128755', 27 | }, 28 | midContainer:{ 29 | justifyContent:'space-around', 30 | }, 31 | time:{ 32 | fontSize:16, 33 | color:'grey', 34 | position:'relative', 35 | zIndex:1, 36 | 37 | }, 38 | }); 39 | 40 | export default styles; -------------------------------------------------------------------------------- /navigation/LinkingConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { LinkingOptions } from '@react-navigation/native'; 2 | import * as Linking from 'expo-linking'; 3 | 4 | import { RootStackParamList } from '../types'; 5 | 6 | const linking: LinkingOptions = { 7 | prefixes: [Linking.createURL('/')], 8 | config: { 9 | screens: { 10 | Root: { 11 | screens: { 12 | Camera: { 13 | screens: { 14 | CameraScreen: 'Camera', 15 | }, 16 | }, 17 | Chats: { 18 | screens: { 19 | ChatScreen: 'Chats', 20 | }, 21 | }, 22 | Status: { 23 | screens: { 24 | StatusScreen: 'Status', 25 | }, 26 | }, 27 | Calls: { 28 | screens: { 29 | CallScreen: 'Calls', 30 | }, 31 | }, 32 | }, 33 | }, 34 | Modal: 'modal', 35 | NotFound: '*', 36 | }, 37 | }, 38 | }; 39 | 40 | export default linking; 41 | -------------------------------------------------------------------------------- /screens/NotFoundScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StyleSheet, TouchableOpacity } from 'react-native'; 2 | 3 | import { Text, View } from '../components/Themed'; 4 | import { RootStackScreenProps } from '../types'; 5 | 6 | export default function NotFoundScreen({ navigation }: RootStackScreenProps<'NotFound'>) { 7 | return ( 8 | 9 | This screen doesn't exist. 10 | navigation.replace('Root')} style={styles.link}> 11 | Go to home screen! 12 | 13 | 14 | ); 15 | } 16 | 17 | const styles = StyleSheet.create({ 18 | container: { 19 | flex: 1, 20 | alignItems: 'center', 21 | justifyContent: 'center', 22 | padding: 20, 23 | }, 24 | title: { 25 | fontSize: 20, 26 | fontWeight: 'bold', 27 | }, 28 | link: { 29 | marginTop: 15, 30 | paddingVertical: 15, 31 | }, 32 | linkText: { 33 | fontSize: 14, 34 | color: '#2e78b7', 35 | }, 36 | }); 37 | -------------------------------------------------------------------------------- /screens/ModalScreen.tsx: -------------------------------------------------------------------------------- 1 | import { StatusBar } from 'expo-status-bar'; 2 | import { Platform, StyleSheet } from 'react-native'; 3 | 4 | import EditScreenInfo from '../components/EditScreenInfo'; 5 | import { Text, View } from '../components/Themed'; 6 | 7 | export default function ModalScreen() { 8 | return ( 9 | 10 | Modal 11 | 12 | 13 | 14 | {/* Use a light status bar on iOS to account for the black space above the modal */} 15 | 16 | 17 | ); 18 | } 19 | 20 | const styles = StyleSheet.create({ 21 | container: { 22 | flex: 1, 23 | alignItems: 'center', 24 | justifyContent: 'center', 25 | }, 26 | title: { 27 | fontSize: 20, 28 | fontWeight: 'bold', 29 | }, 30 | separator: { 31 | marginVertical: 30, 32 | height: 1, 33 | width: '80%', 34 | }, 35 | }); 36 | -------------------------------------------------------------------------------- /components/chatMessage/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from 'react-native' 2 | import React from 'react' 3 | import { Message } from '../../types' 4 | import styles from './style' 5 | import moment from 'moment'; 6 | import Colors from '../../constants/Colors'; 7 | 8 | export type chatMessageProps = { 9 | message: Message; 10 | } 11 | 12 | const ChatMessage = (props: chatMessageProps) => { 13 | const { message } = props; 14 | const isMyMessage = () => { 15 | return message.user.id === 'u1' 16 | } 17 | return ( 18 | 19 | 24 | {!isMyMessage() && {message.user.name}} 25 | {message.content} 26 | {moment(message.createdAt).fromNow()} 27 | 28 | 29 | ) 30 | } 31 | 32 | export default ChatMessage -------------------------------------------------------------------------------- /hooks/useCachedResources.ts: -------------------------------------------------------------------------------- 1 | import { FontAwesome } from '@expo/vector-icons'; 2 | import * as Font from 'expo-font'; 3 | import * as SplashScreen from 'expo-splash-screen'; 4 | import { useEffect, useState } from 'react'; 5 | 6 | export default function useCachedResources() { 7 | const [isLoadingComplete, setLoadingComplete] = useState(false); 8 | 9 | // Load any resources or data that we need prior to rendering the app 10 | useEffect(() => { 11 | async function loadResourcesAndDataAsync() { 12 | try { 13 | SplashScreen.preventAutoHideAsync(); 14 | 15 | // Load fonts 16 | await Font.loadAsync({ 17 | ...FontAwesome.font, 18 | 'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'), 19 | }); 20 | } catch (e) { 21 | // We might want to provide this error information to an error reporting service 22 | console.warn(e); 23 | } finally { 24 | setLoadingComplete(true); 25 | SplashScreen.hideAsync(); 26 | } 27 | } 28 | 29 | loadResourcesAndDataAsync(); 30 | }, []); 31 | 32 | return isLoadingComplete; 33 | } 34 | -------------------------------------------------------------------------------- /constants/data/Users.ts: -------------------------------------------------------------------------------- 1 | export default [{ 2 | id: 'u1', 3 | name: 'Vadim', 4 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/1.jpg', 5 | status: "Hello there, how are you" 6 | }, { 7 | id: 'u2', 8 | name: 'Lukas', 9 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/2.jpg', 10 | }, { 11 | id: 'u3', 12 | name: 'Daniil', 13 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/3.jpg', 14 | }, { 15 | id: 'u4', 16 | name: 'Alex', 17 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/3.png', 18 | }, { 19 | id: 'u5', 20 | name: 'Vlad', 21 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/4.jpg', 22 | }, { 23 | id: 'u6', 24 | name: 'Elon Musk', 25 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/5.jpg', 26 | }, { 27 | id: 'u7', 28 | name: 'Adrian', 29 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/6.png', 30 | }, { 31 | id: 'u8', 32 | name: 'Borja', 33 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/7.png', 34 | }, { 35 | id: 'u9', 36 | name: 'Mom', 37 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/8.png', 38 | }, { 39 | id: 'u10', 40 | name: 'Angelina Jolie', 41 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/9.png', 42 | }] 43 | -------------------------------------------------------------------------------- /components/Themed.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about Light and Dark modes: 3 | * https://docs.expo.io/guides/color-schemes/ 4 | */ 5 | 6 | import { Text as DefaultText, View as DefaultView } from 'react-native'; 7 | 8 | import Colors from '../constants/Colors'; 9 | import useColorScheme from '../hooks/useColorScheme'; 10 | 11 | export function useThemeColor( 12 | props: { light?: string; dark?: string }, 13 | colorName: keyof typeof Colors.light & keyof typeof Colors.dark 14 | ) { 15 | const theme = useColorScheme(); 16 | const colorFromProps = props[theme]; 17 | 18 | if (colorFromProps) { 19 | return colorFromProps; 20 | } else { 21 | return Colors[theme][colorName]; 22 | } 23 | } 24 | 25 | type ThemeProps = { 26 | lightColor?: string; 27 | darkColor?: string; 28 | }; 29 | 30 | export type TextProps = ThemeProps & DefaultText['props']; 31 | export type ViewProps = ThemeProps & DefaultView['props']; 32 | 33 | export function Text(props: TextProps) { 34 | const { style, lightColor, darkColor, ...otherProps } = props; 35 | const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); 36 | 37 | return ; 38 | } 39 | 40 | export function View(props: ViewProps) { 41 | const { style, lightColor, darkColor, ...otherProps } = props; 42 | const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); 43 | 44 | return ; 45 | } 46 | -------------------------------------------------------------------------------- /types.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Learn more about using TypeScript with React Navigation: 3 | * https://reactnavigation.org/docs/typescript/ 4 | */ 5 | 6 | import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'; 7 | import { CompositeScreenProps, NavigatorScreenParams } from '@react-navigation/native'; 8 | import { NativeStackScreenProps } from '@react-navigation/native-stack'; 9 | 10 | declare global { 11 | namespace ReactNavigation { 12 | interface RootParamList extends RootStackParamList {} 13 | } 14 | } 15 | 16 | export type RootStackParamList = { 17 | Root: NavigatorScreenParams | undefined; 18 | Modal: undefined; 19 | NotFound: undefined; 20 | ChatRoom: undefined; 21 | Contact:undefined; 22 | }; 23 | 24 | export type RootStackScreenProps = NativeStackScreenProps< 25 | RootStackParamList, 26 | Screen 27 | >; 28 | 29 | export type RootTabParamList = { 30 | Camera: undefined; 31 | Chats: undefined; 32 | Status: undefined; 33 | Calls: undefined; 34 | }; 35 | 36 | export type RootTabScreenProps = CompositeScreenProps< 37 | BottomTabScreenProps, 38 | NativeStackScreenProps 39 | >; 40 | 41 | export type users = { 42 | id:String; 43 | name:String; 44 | imageUri: String; 45 | 46 | }; 47 | 48 | export type Message = { 49 | id: String; 50 | content: String; 51 | createdAt: String; 52 | user:users; 53 | }; 54 | 55 | export type chatRoom = { 56 | id: string; 57 | users:[users]; 58 | lastMessage:Message; 59 | }; 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WhatsAppNew", 3 | "version": "1.0.0", 4 | "main": "node_modules/expo/AppEntry.js", 5 | "scripts": { 6 | "start": "expo start", 7 | "android": "expo start --android", 8 | "ios": "expo start --ios", 9 | "web": "expo start --web", 10 | "test": "jest --watchAll" 11 | }, 12 | "jest": { 13 | "preset": "jest-expo" 14 | }, 15 | "dependencies": { 16 | "@expo/vector-icons": "^13.0.0", 17 | "@react-navigation/bottom-tabs": "^6.0.5", 18 | "@react-navigation/material-top-tabs": "^6.2.4", 19 | "@react-navigation/native": "^6.0.2", 20 | "@react-navigation/native-stack": "^6.1.0", 21 | "expo": "~46.0.9", 22 | "expo-asset": "~8.6.1", 23 | "expo-constants": "~13.2.4", 24 | "expo-font": "~10.2.0", 25 | "expo-linking": "~3.2.2", 26 | "expo-splash-screen": "~0.16.2", 27 | "expo-status-bar": "~1.4.0", 28 | "expo-system-ui": "~1.3.0", 29 | "expo-web-browser": "~11.0.0", 30 | "moment": "^2.29.4", 31 | "react": "18.0.0", 32 | "react-dom": "18.0.0", 33 | "react-native": "0.69.5", 34 | "react-native-pager-view": "5.4.24", 35 | "react-native-reanimated": "~2.9.1", 36 | "react-native-safe-area-context": "4.3.1", 37 | "react-native-screens": "~3.15.0", 38 | "react-native-tab-view": "^3.1.1", 39 | "react-native-web": "~0.18.7" 40 | }, 41 | "devDependencies": { 42 | "@babel/core": "^7.12.9", 43 | "@types/react": "~18.0.14", 44 | "@types/react-native": "~0.69.1", 45 | "jest": "^26.6.3", 46 | "jest-expo": "~44.0.1", 47 | "react-test-renderer": "18.0.0", 48 | "typescript": "~4.3.5" 49 | }, 50 | "private": true 51 | } 52 | -------------------------------------------------------------------------------- /components/chatList/index.tsx: -------------------------------------------------------------------------------- 1 | import { useNavigation } from "@react-navigation/native"; 2 | import moment from "moment"; 3 | import React from "react"; 4 | import { Image, Text, TouchableOpacity, View, Alert } from "react-native"; 5 | import { chatRoom } from "../../types"; 6 | import styles from "./style"; 7 | 8 | export type ChatListItemProps = { 9 | chatRoom: chatRoom; 10 | } 11 | 12 | const ChatListItem = (props: ChatListItemProps) => { 13 | const { chatRoom } = props; 14 | const user = chatRoom.users[1]; 15 | const navigation = useNavigation() 16 | const onClick = () => { 17 | navigation.navigate('ChatRoom', { 18 | id: chatRoom.id, 19 | user:user.name, 20 | img:user.imageUri, 21 | }) 22 | } 23 | const onClickc = () => { 24 | alert("Clicked") 25 | } 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {user.name} 36 | {chatRoom.lastMessage.content} 37 | 38 | 39 | {moment(chatRoom.lastMessage.createdAt).format("DD/MM/YYYY")} 40 | 41 | 42 | ) 43 | } 44 | 45 | export default ChatListItem -------------------------------------------------------------------------------- /components/inputBox/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, TextInput, TouchableOpacity } from 'react-native' 2 | import React from 'react' 3 | import styles from './style' 4 | import { Entypo, Feather, FontAwesome5, Fontisto, MaterialCommunityIcons } from '@expo/vector-icons' 5 | import Colors from '../../constants/Colors' 6 | 7 | const InputComp = () => { 8 | const [message,setMessage] = React.useState('') 9 | const sendMessage = () => { 10 | console.warn("Send Message") 11 | } 12 | const openCamera = () => { 13 | console.warn("Open camera media") 14 | } 15 | 16 | const recordVoiceNote = () => { 17 | console.warn("Open camera media") 18 | } 19 | 20 | return ( 21 | 22 | 23 | 24 | 31 | 32 | {!message && 33 | 34 | 35 | } 36 | 37 | 38 | {!message? 39 | 40 | 41 | : 42 | 43 | 44 | 45 | } 46 | 47 | 48 | ) 49 | } 50 | 51 | export default InputComp -------------------------------------------------------------------------------- /constants/data/Chats.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | id: '1', 3 | users: [{ 4 | id: 'u1', 5 | name: 'Mustapha', 6 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/1.jpg', 7 | }, { 8 | id: 'u2', 9 | name: 'Gtan', 10 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/2.jpg', 11 | }], 12 | messages: [{ 13 | id: 'm1', 14 | content: 'How are you, Gtan!', 15 | createdAt: '2022-10-10T12:48:00.000Z', 16 | user: { 17 | id: 'u1', 18 | name: 'Mustapha', 19 | }, 20 | }, { 21 | id: 'm2', 22 | content: 'I am good, good', 23 | createdAt: '2022-10-03T14:49:00.000Z', 24 | user: { 25 | id: 'u2', 26 | name: 'Gtan', 27 | }, 28 | }, { 29 | id: 'm3', 30 | content: 'What about you?', 31 | createdAt: '2022-10-03T14:49:40.000Z', 32 | user: { 33 | id: 'u2', 34 | name: 'Gtan', 35 | }, 36 | }, { 37 | id: 'm4', 38 | content: 'Good as well, preparing for the stream now.', 39 | createdAt: '2022-09-30T14:50:00.000Z', 40 | user: { 41 | id: 'u1', 42 | name: 'Mustapha', 43 | }, 44 | }, { 45 | id: 'm5', 46 | content: 'How is your uni going?', 47 | createdAt: '2022-10-03T14:51:00.000Z', 48 | user: { 49 | id: 'u1', 50 | name: 'Mustapha', 51 | }, 52 | }, { 53 | id: 'm6', 54 | content: 'It is a bit tough, as I have 2 specializations. How about yours? Do you enjoy it?', 55 | createdAt: '2022-10-03T14:49:00.000Z', 56 | user: { 57 | id: 'u2', 58 | name: 'Gtan', 59 | }, 60 | }, { 61 | id: 'm7', 62 | content: 'Big Data is really interesting. Cannot wait to go through all the material.', 63 | createdAt: '2022-10-03T14:53:00.000Z', 64 | user: { 65 | id: 'u1', 66 | name: 'Mustapha', 67 | }, 68 | },{ 69 | id: 'm8', 70 | content: 'You must work hard get success to change life', 71 | createdAt: '2022-10-01T05:44:00.000Z', 72 | user: { 73 | id: 'u1', 74 | name: 'Mustapha', 75 | }, 76 | }, { 77 | id: 'm9', 78 | content: 'It is a bit tough, as I have 2 specializations. How about yours? Do you enjoy it?', 79 | createdAt: '2022-10-01T05:51:00.000Z', 80 | user: { 81 | id: 'u2', 82 | name: 'Gtan', 83 | }, 84 | }] 85 | } 86 | 87 | -------------------------------------------------------------------------------- /constants/data/ChatRooms.ts: -------------------------------------------------------------------------------- 1 | export default [{ 2 | id: '1', 3 | users: [{ 4 | id: 'u1', 5 | name: 'Mustapha', 6 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 7 | }, { 8 | id: 'u2', 9 | name: 'Musocial', 10 | imageUri: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTh8fHByb2ZpbGV8ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60', 11 | }], 12 | lastMessage: { 13 | id: 'm1', 14 | content: 'Well done this sprint, guys!', 15 | createdAt: '2020-10-03T14:48:00.000Z', 16 | } 17 | }, { 18 | id: '2', 19 | users: [{ 20 | id: 'u1', 21 | name: 'Mustapha', 22 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 23 | }, { 24 | id: 'u3', 25 | name: 'Amina', 26 | imageUri: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1374&q=80', 27 | }], 28 | lastMessage: { 29 | id: 'm2', 30 | content: 'How are you doing?', 31 | createdAt: '2020-10-02T15:40:00.000Z', 32 | } 33 | }, { 34 | id: '3', 35 | users: [{ 36 | id: 'u1', 37 | name: 'Mustapha', 38 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 39 | }, { 40 | id: 'u4', 41 | name: 'John', 42 | imageUri: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTV8fHByb2ZpbGV8ZW58MHx8MHx8&auto=format&fit=crop&w=500&q=60', 43 | }], 44 | lastMessage: { 45 | id: 'm3', 46 | content: 'Hi, Mereweneza John.', 47 | createdAt: '2020-10-02T14:48:00.000Z', 48 | } 49 | }, { 50 | id: '4', 51 | users: [{ 52 | id: 'u1', 53 | name: 'Mustapha', 54 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 55 | }, { 56 | id: 'u5', 57 | name: 'Gabriel', 58 | imageUri: 'https://images.unsplash.com/photo-1511367461989-f85a21fda167?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1031&q=80', 59 | }], 60 | lastMessage: { 61 | id: 'm4', 62 | content: 'How do you feel coding..? Do you think I am wrong about my stupid answers...?', 63 | createdAt: '2020-09-29T14:48:00.000Z', 64 | } 65 | }, { 66 | id: '5', 67 | users: [{ 68 | id: 'u1', 69 | name: 'Mustapha', 70 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 71 | }, { 72 | id: 'u6', 73 | name: 'Gtan', 74 | imageUri: 'https://notjustdev-dummy.s3.us-east-2.amazonaws.com/avatars/5.jpg', 75 | }], 76 | lastMessage: { 77 | id: 'm5', 78 | content: 'What is going on with coding?', 79 | createdAt: '2020-09-30T14:48:00.000Z', 80 | } 81 | }, { 82 | id: '6', 83 | users: [{ 84 | id: 'u1', 85 | name: 'Mustapha', 86 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 87 | }, { 88 | id: 'u7', 89 | name: 'Alice', 90 | imageUri: 'https://images.unsplash.com/photo-1618641986557-1ecd230959aa?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8cHJvZmlsZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60', 91 | }], 92 | lastMessage: { 93 | id: 'm6', 94 | content: 'I have a solution', 95 | createdAt: '2020-10-02T15:40:00.000Z', 96 | } 97 | }, { 98 | id: '7', 99 | users: [{ 100 | id: 'u1', 101 | name: 'Mustapha', 102 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 103 | }, { 104 | id: 'u8', 105 | name: 'Theoneste', 106 | imageUri: 'https://images.unsplash.com/photo-1618641986557-1ecd230959aa?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NHx8cHJvZmlsZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60', 107 | }], 108 | lastMessage: { 109 | id: 'm7', 110 | content: 'How are you doing?', 111 | createdAt: '2020-10-02T15:40:00.000Z', 112 | } 113 | }, { 114 | id: '8', 115 | users: [{ 116 | id: 'u1', 117 | name: 'Mustapha', 118 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 119 | }, { 120 | id: 'u9', 121 | name: 'Mom', 122 | imageUri: 'https://images.unsplash.com/photo-1474447976065-67d23accb1e3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8cHJvZmlsZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60', 123 | }], 124 | lastMessage: { 125 | id: 'm8', 126 | content: 'Dear, did you eat?', 127 | createdAt: '2020-09-27T15:40:00.000Z', 128 | } 129 | }, { 130 | id: '9', 131 | users: [{ 132 | id: 'u1', 133 | name: 'Mustapha', 134 | imageUri: 'https://unsplash.com/photos/WNoLnJo7tS8', 135 | }, { 136 | id: 'u10', 137 | name: 'Giramata Teckla', 138 | imageUri: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8cHJvZmlsZXxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=500&q=60', 139 | }], 140 | lastMessage: { 141 | id: 'm9', 142 | content: 'You are the best caipine in IPRC tumpa', 143 | createdAt: '2020-09-25T15:40:00.000Z', 144 | }, 145 | }] 146 | -------------------------------------------------------------------------------- /navigation/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * If you are not familiar with React Navigation, refer to the "Fundamentals" guide: 3 | * https://reactnavigation.org/docs/getting-started 4 | * 5 | */ 6 | import { Entypo, Feather, FontAwesome, FontAwesome5, Ionicons, MaterialIcons } from '@expo/vector-icons'; 7 | import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'; 8 | import { NavigationContainer, DefaultTheme, DarkTheme, useNavigation } from '@react-navigation/native'; 9 | import { createNativeStackNavigator } from '@react-navigation/native-stack'; 10 | import * as React from 'react'; 11 | import { Button, ColorSchemeName, Image,View,Text, Touchable, TouchableOpacity } from 'react-native'; 12 | 13 | import Colors from '../constants/Colors'; 14 | import useColorScheme from '../hooks/useColorScheme'; 15 | import ModalScreen from '../screens/ModalScreen'; 16 | import NotFoundScreen from '../screens/NotFoundScreen'; 17 | import { RootStackParamList, RootTabParamList, RootTabScreenProps } from '../types'; 18 | import LinkingConfiguration from './LinkingConfiguration'; 19 | import ChatScreen from '../screens/ChatScreen'; 20 | import CameraScreen from '../screens/CameraScreen'; 21 | import CallScreen from '../screens/CallScreen'; 22 | import StatusScreen from '../screens/StatusScreen'; 23 | import ChatRoomScreen from '../screens/ChatRoomScreen'; 24 | import ContactScreen from '../screens/ContactScreen'; 25 | 26 | export default function Navigation({ colorScheme }: { colorScheme: ColorSchemeName }) { 27 | return ( 28 | 31 | 32 | 33 | ); 34 | } 35 | 36 | 37 | const Stack = createNativeStackNavigator(); 38 | 39 | function RootNavigator() { 40 | const [moon,setMoon] = React.useState(true); 41 | const [offline,setOffline] = React.useState(false) 42 | const navigation = useNavigation() 43 | return ( 44 | 57 | ( 59 | 60 | setOffline(!offline)}> 61 | 62 | 63 | setMoon(!moon)}> 64 | 65 | 66 | 67 | 68 | 69 | ),}} /> 70 | ({ 71 | title: route.params.user, 72 | headerRight:()=>( 73 | 74 | 75 | 76 | 77 | 78 | ) , 79 | headerLeft:()=>( 80 | navigation.goBack()}> 81 | 82 | 83 | 84 | 85 | 86 | ), 87 | })}/> 88 | 89 | 90 | 91 | 92 | 93 | 94 | ); 95 | } 96 | 97 | 98 | const TopTab = createMaterialTopTabNavigator(); 99 | 100 | function TopTabNavigator() { 101 | const colorScheme = useColorScheme(); 102 | 103 | return ( 104 | 112 | , 113 | tabBarLabel:()=>null}}/> 114 | 115 | 116 | 117 | 118 | ); 119 | } 120 | 121 | 122 | function TabBarIcon(props: { 123 | name: React.ComponentProps['name']; 124 | color: string; 125 | }) { 126 | return ; 127 | } 128 | --------------------------------------------------------------------------------