Update chat screen and add a StubMessageService
continuous-integration/drone/push Build is passing Details

pull/19/head
Emre KARTAL 1 year ago
parent d2421812e2
commit b746fbf7d2

@ -116,7 +116,7 @@ Une fois sur la page, saisissez votre nom, votre adresse e-mail, et votre mot de
Pour accéder aux détails d'une musique, maintenez votre doigt appuyé sur un Spot ou rendez-vous sur la page des favoris. Vous pourrez écouter la musique :arrow_forward:, obtenir des informations sur l'artiste et la chanson, découvrir des musiques similaires, et même l'ajouter à votre playlist Spotify ou la partager. Pour accéder aux détails d'une musique, maintenez votre doigt appuyé sur un Spot ou rendez-vous sur la page des favoris. Vous pourrez écouter la musique :arrow_forward:, obtenir des informations sur l'artiste et la chanson, découvrir des musiques similaires, et même l'ajouter à votre playlist Spotify ou la partager.
<br/> <br/>
`Dans la page **settings** ⚙️, vous avez accès à toutes vos informations ```Spotify```, que vous pouvez modifier à votre guise. Toutefois, ces modifications ne seront prises en compte que dans notre application. Vous pouvez également choisir le mode sombre (dark mode) dans les paramètres pour une expérience de navigation plus confortable. Dans la page **settings** ⚙️, vous avez accès à toutes vos informations ```Spotify```, que vous pouvez modifier à votre guise. Toutefois, ces modifications ne seront prises en compte que dans notre application. Vous pouvez également choisir le mode sombre (dark mode) dans les paramètres pour une expérience de navigation plus confortable.
<br/> <br/>
### Voici un petit récapitulatif ### Voici un petit récapitulatif

@ -1,4 +1,4 @@
import { Router, Request, Response, NextFunction } from 'express'; import { Router, Request, Response } from 'express';
import IController from './interfaces/IController'; import IController from './interfaces/IController';
import User from '../models/User'; import User from '../models/User';
import UserService from '../services/UserService'; import UserService from '../services/UserService';

@ -38,7 +38,7 @@ const userSchema = new Schema({
userId: String, userId: String,
date: Date date: Date
}], }],
default: [] default: []
} }
}, },
{ timestamps: true } { timestamps: true }

@ -4,11 +4,12 @@ import { useSelector } from 'react-redux';
import { colorsDark } from '../constants/colorsDark'; import { colorsDark } from '../constants/colorsDark';
import { colorsLight } from '../constants/colorsLight'; import { colorsLight } from '../constants/colorsLight';
import normalize from './Normalize'; import normalize from './Normalize';
import Message from '../models/Message';
type FriendProps = { type FriendProps = {
image: string; image: string;
name: string; name: string;
lastMessage: string; lastMessage: Message;
} }
export default function Friend(props: FriendProps) { export default function Friend(props: FriendProps) {
@ -67,14 +68,41 @@ export default function Friend(props: FriendProps) {
} }
}) })
const getTimeDifferenceString = (date: Date): string => {
const now = new Date();
const differenceInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
const intervals = {
an: 31536000,
mois: 2592000,
sem: 604800,
jour: 86400,
heure: 3600,
min: 60,
};
for (const [intervalName, seconds] of Object.entries(intervals)) {
const intervalCount = Math.floor(differenceInSeconds / seconds);
if (intervalCount > 0) {
if (intervalName === 'mois' || intervalName === 'min') {
return `il y a ${intervalCount} ${intervalName}`;
} else {
return `il y a ${intervalCount} ${intervalName}${intervalCount !== 1 ? 's' : ''}`;
}
}
}
return 'À linstant';
};
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Image style={styles.image} source={source} /> <Image style={styles.image} source={source} />
<View style={styles.profilContainer}> <View style={styles.profilContainer}>
<Text style={styles.name} numberOfLines={1}>{props.name}</Text> <Text style={styles.name} numberOfLines={1}>{props.name}</Text>
<View style={styles.lastMessageContainer}> <View style={styles.lastMessageContainer}>
<Text style={styles.lastMessage} numberOfLines={1}>{props.lastMessage}</Text> <Text style={styles.lastMessage} numberOfLines={1}>{props.lastMessage.content}</Text>
<Text style={styles.time}> · 1sem</Text> <Text style={styles.time}> · {getTimeDifferenceString(props.lastMessage.date)}</Text>
</View> </View>
</View> </View>
<Image style={styles.button} source={require('../assets/images/chevron_right_icon.png')} /> <Image style={styles.button} source={require('../assets/images/chevron_right_icon.png')} />

@ -8,7 +8,7 @@ export default function Paginator({ data, scrollX }) {
return ( return (
<View style={{ flexDirection: 'row', height: 64, marginBottom: normalize(50) }}> <View style={{ flexDirection: 'row', height: 64, marginBottom: normalize(50) }}>
{data.map((_ : any, i : any) => { { data.map((_ : any, i : any) => {
const inputRange = [(i - 1) * width, i * width, (i + 1) * width]; const inputRange = [(i - 1) * width, i * width, (i + 1) * width];
const dotWidth = scrollX.interpolate({ const dotWidth = scrollX.interpolate({

@ -3,7 +3,7 @@ import Music from '../models/Music';
import normalize from './Normalize'; import normalize from './Normalize';
export interface RenderCellProps { export interface RenderCellProps {
music : Music; music: Music;
} }
export const SimilarMusic = (props: RenderCellProps) => { export const SimilarMusic = (props: RenderCellProps) => {
return ( return (

@ -0,0 +1,47 @@
import Message from "./Message";
export default class Conversation {
private _id: string;
private _name: string;
private _image: string;
private _lastMessage: Message;
constructor(id: string, name: string, image: string, lastMessage: Message) {
this._id = id;
this._name = name;
this._image = image;
this._lastMessage = lastMessage;
}
get id(): string {
return this._id;
}
set id(value: string) {
this._id = value;
}
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
get image(): string {
return this._image;
}
set image(value: string) {
this._image = value;
}
get lastMessage(): Message {
return this._lastMessage;
}
set lastMessage(value: Message) {
this._lastMessage = value;
}
}

@ -0,0 +1,55 @@
export default class Message {
private _id: string;
private _content: string;
private _sender: string;
private _date: Date;
private _audio: string;
constructor(id: string, content: string, sender: string, date: Date, audio: string = '') {
this._id = id;
this._content = content;
this._sender = sender;
this._date = date;
this._audio = audio;
}
get id(): string {
return this._id;
}
set id(value: string) {
this._id = value;
}
get content(): string {
return this._content;
}
set content(value: string) {
this._content = value;
}
get sender(): string {
return this._sender;
}
set sender(value: string) {
this._sender = value;
}
get date(): Date {
return this._date;
}
set date(value: Date) {
this._date = value;
}
get audio(): string {
return this._audio;
}
set audio(value: string) {
this._audio = value;
}
}

@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { View, Alert, Platform } from 'react-native'; import { View, Alert, Platform } from 'react-native';
import { faUser, faEnvelope, faHeart, faMusic } from "@fortawesome/free-solid-svg-icons" import { faUser, faEnvelope, faHeart, faMusic } from "@fortawesome/free-solid-svg-icons"
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { NavigationContainer } from '@react-navigation/native'; import { NavigationContainer, getFocusedRouteNameFromRoute } from '@react-navigation/native';
import FavoriteNavigation from './FavoriteNavigation'; import FavoriteNavigation from './FavoriteNavigation';
import SettingNavigation from './SettingNavigation'; import SettingNavigation from './SettingNavigation';
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
@ -156,10 +156,15 @@ export default function HomeNavigation() {
tabBarIcon: ({ color }) => <View><TabBarIcon name={faHeart} color={color} size={23} /></View>, tabBarIcon: ({ color }) => <View><TabBarIcon name={faHeart} color={color} size={23} /></View>,
}} /> }} />
<BottomTabNavigator.Screen name="Messages" component={MessagingNavigation} <BottomTabNavigator.Screen name="Messages" component={MessagingNavigation}
options={{ options={({ route }) => ({
headerShown: false, headerShown: false,
tabBarStyle: {
display: getFocusedRouteNameFromRoute(route) !== "Chat" ? "flex" : "none",
position: "absolute",
borderTopColor: isDark ? 'rgba(255, 255, 255, 0.25)' : 'rgba(50, 50, 50, 0.07)',
},
tabBarIcon: ({ color }) => <View ><TabBarIcon name={faEnvelope} color={color} size={23} /></View>, tabBarIcon: ({ color }) => <View ><TabBarIcon name={faEnvelope} color={color} size={23} /></View>,
}} /> })} />
<BottomTabNavigator.Screen name="Profil" component={SettingNavigation} <BottomTabNavigator.Screen name="Profil" component={SettingNavigation}
options={{ options={{
headerShown: false, headerShown: false,

@ -1,12 +1,38 @@
import React from 'react'; import React from 'react';
import ConversationScreen from '../screens/ConversationScreen' import ConversationScreen from '../screens/ConversationScreen'
import { Image, View, Text, StyleSheet } from 'react-native';
import ChatScreen from '../screens/ChatScreen'; import ChatScreen from '../screens/ChatScreen';
import { createStackNavigator } from '@react-navigation/stack'; import { createStackNavigator } from '@react-navigation/stack';
import { colorsDark } from "../constants/colorsDark";
import { colorsLight } from "../constants/colorsLight";
import { useSelector } from 'react-redux';
export default function MessagingNavigation() { export default function MessagingNavigation() {
// @ts-ignore
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? colorsDark : colorsLight;
const Stack = createStackNavigator(); const Stack = createStackNavigator();
const styles = StyleSheet.create({
headerContainer: {
flexDirection: 'row',
alignItems: 'center'
},
headerImage: {
width: 30,
height: 30,
borderRadius: 20,
marginRight: 8
},
headerText: {
color: style.Text,
fontSize: 16,
fontWeight: 'bold'
}
});
return ( return (
<Stack.Navigator initialRouteName="Conversation" > <Stack.Navigator initialRouteName="Conversation">
<Stack.Screen <Stack.Screen
name="Conversation" name="Conversation"
component={ConversationScreen} component={ConversationScreen}
@ -15,7 +41,29 @@ export default function MessagingNavigation() {
<Stack.Screen <Stack.Screen
name="Chat" name="Chat"
component={ChatScreen} component={ChatScreen}
options={{ headerShown: false }} options={({ route }) => ({
headerShown: true,
headerBackTitleVisible: false,
headerStyle: {
backgroundColor: style.Card
},
headerTitle: () => (
<View style={styles.headerContainer}>
<Image
// @ts-ignore
source={{ uri: route.params.image }}
style={styles.headerImage}
/>
<Text style={styles.headerText}>
{/* @ts-ignore */}
{route.params.username}
</Text>
</View>
),
headerTitleStyle: {
color: style.Text
},
})}
/> />
</Stack.Navigator> </Stack.Navigator>
) )

@ -25,6 +25,7 @@
"expo-image-picker": "~14.0.2", "expo-image-picker": "~14.0.2",
"expo-linear-gradient": "~12.0.1", "expo-linear-gradient": "~12.0.1",
"expo-location": "~15.0.1", "expo-location": "~15.0.1",
"expo-random": "^13.0.0",
"expo-secure-store": "~12.0.0", "expo-secure-store": "~12.0.0",
"expo-splash-screen": "~0.17.5", "expo-splash-screen": "~0.17.5",
"react": "18.1.0", "react": "18.1.0",
@ -37,8 +38,9 @@
"react-native-safe-area-context": "4.4.1", "react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0", "react-native-screens": "~3.18.0",
"react-native-svg": "13.4.0", "react-native-svg": "13.4.0",
"react-navigation-shared-element": "^3.1.3", "react-native-vector-icons": "^10.0.3",
"react-native-web": "~0.18.9", "react-native-web": "~0.18.9",
"react-navigation-shared-element": "^3.1.3",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",
"redux": "^4.2.1" "redux": "^4.2.1"
}, },
@ -46,6 +48,7 @@
"@babel/core": "^7.12.9", "@babel/core": "^7.12.9",
"@types/react": "~18.0.14", "@types/react": "~18.0.14",
"@types/react-native": "~0.70.8", "@types/react-native": "~0.70.8",
"@types/react-native-vector-icons": "^6.4.18",
"typescript": "^4.6.3" "typescript": "^4.6.3"
}, },
"private": true "private": true

@ -1,5 +1,8 @@
import Conversation from "../../models/Conversation";
import Message from "../../models/Message";
import Music from "../../models/Music"; import Music from "../../models/Music";
import { Spot } from "../../models/Spot"; import { Spot } from "../../models/Spot";
import { chatTypes } from "../types/chatTypes";
import { favoritesTypes } from "../types/favoritesTypes"; import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes"; import { spotifyTypes } from "../types/spotifyTypes";
@ -28,4 +31,18 @@ export const resetNbAddedFavoriteMusic = () => {
return { return {
type: favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC type: favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC
}; };
}
export const setConversations = (conversations: Conversation[]) => {
return {
type: chatTypes.FETCH_CONVERSATIONS,
payload: conversations,
};
}
export const setMessages = (messages: Message[]) => {
return {
type: chatTypes.FETCH_MESSAGES,
payload: messages,
};
} }

@ -1,4 +1,7 @@
import Conversation from "../../models/Conversation";
import Message from "../../models/Message";
import { Spot } from "../../models/Spot"; import { Spot } from "../../models/Spot";
import { chatTypes } from "../types/chatTypes";
import { favoritesTypes } from "../types/favoritesTypes"; import { favoritesTypes } from "../types/favoritesTypes";
import { spotifyTypes } from "../types/spotifyTypes"; import { spotifyTypes } from "../types/spotifyTypes";
import { spotTypes } from "../types/spotTypes"; import { spotTypes } from "../types/spotTypes";
@ -10,6 +13,8 @@ const initialState = {
userCurrentMusic: null, userCurrentMusic: null,
nbAddedFavoriteMusic: 0, nbAddedFavoriteMusic: 0,
oldSpot: [] as string[], oldSpot: [] as string[],
conversations: [] as Conversation[],
messages: [] as Message[]
} }
const appReducer = (state = initialState, action: any) => { const appReducer = (state = initialState, action: any) => {
@ -23,6 +28,10 @@ const appReducer = (state = initialState, action: any) => {
}; };
case favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC: case favoritesTypes.RESET_NB_ADDED_FAVORITE_MUSIC:
return { ...state, nbAddedFavoriteMusic: 0 }; return { ...state, nbAddedFavoriteMusic: 0 };
case chatTypes.FETCH_CONVERSATIONS:
return { ...state, conversations: action.payload };
case chatTypes.FETCH_MESSAGES:
return { ...state, messages: action.payload };
case spotTypes.FETCH_SPOT: case spotTypes.FETCH_SPOT:
const uniqueSpots = action.payload.filter((spot: Spot) => { const uniqueSpots = action.payload.filter((spot: Spot) => {
const spotKey = `${spot.user}_${spot.music.id}`; const spotKey = `${spot.user}_${spot.music.id}`;

@ -28,6 +28,7 @@ export const getUserCurrentMusic = () => {
const music = await MusicServiceProvider.musicService.getMusicById(idTrack); const music = await MusicServiceProvider.musicService.getMusicById(idTrack);
dispatch(setUserCurrentMusic(music)) dispatch(setUserCurrentMusic(music))
} catch (error: any) { } catch (error: any) {
console.log(error);
switch (error.response.status) { switch (error.response.status) {
case 401: case 401:
dispatch(logout); dispatch(logout);

@ -0,0 +1,42 @@
import Message from "../../models/Message";
import IMessageService from "../../services/messages/interfaces/IMessageService"
import StubMessageService from "../../services/messages/stub/StubMessageService";
import { setConversations, setMessages } from "../actions/appActions";
const chatService: IMessageService = new StubMessageService();
export const getConversations = () => {
//@ts-ignore
return async dispatch => {
try {
const conversations = await chatService.getConversations();
dispatch(setConversations(conversations));
} catch (error: any) {
}
}
}
export const getMessages = (id: string) => {
//@ts-ignore
return async dispatch => {
try {
const messages = await chatService.getMessagesWithIdConversation(id);
dispatch(setMessages(messages));
} catch (error: any) {
}
}
}
export const sendMessage = (id: string, message: Message) => {
//@ts-ignore
return async dispatch => {
try {
await chatService.sendMessage(id, message);
dispatch(getMessages(id));
} catch (error: any) {
}
}
}

@ -0,0 +1,4 @@
export const chatTypes = {
FETCH_CONVERSATIONS: 'FETCH_CONVERSATIONS',
FETCH_MESSAGES: 'FETCH_MESSAGES',
}

@ -1,22 +1,178 @@
import { useNavigation } from "@react-navigation/native"; import React, { useCallback, useEffect, useState } from "react";
import React, { useEffect } from "react"; import { Bubble, GiftedChat, IMessage, InputToolbar, Send } from "react-native-gifted-chat";
import { GiftedChat } from "react-native-gifted-chat"; import { faFileImage, faMicrophone } from "@fortawesome/free-solid-svg-icons"
import { colorsDark } from "../constants/colorsDark";
import { colorsLight } from "../constants/colorsLight";
import { useDispatch, useSelector } from 'react-redux';
import { SafeAreaView, TouchableOpacity, View } from "react-native";
import Icon from 'react-native-vector-icons/Ionicons';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import Message from "../models/Message";
import { getMessages, sendMessage } from "../redux/thunk/chatThunk";
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
export default function Chat() { //@ts-ignore
export default function Chat({ route }) {
const item: string = route.params.conversation;
const [messages, setMessages] = useState<IMessage[]>();
//@ts-ignore
const conversations: Message[] = useSelector(state => state.appReducer.messages);
const navigation = useNavigation(); // @ts-ignore
const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? colorsDark : colorsLight;
const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
navigation.getParent()?.setOptions({ // @ts-ignore
tabBarStyle: { dispatch(getMessages(item));
display: "none" }, []);
}
}); useEffect(() => {
return () => navigation.getParent()?.setOptions({ const mappedMessages = conversations.map((msg: Message) => ({
tabBarStyle: undefined _id: msg.id,
text: msg.content,
createdAt: msg.date,
user: {
_id: msg.sender,
name: msg.sender,
avatar: 'https://picsum.photos/536/354',
},
audio: msg.audio
}));
mappedMessages.reverse();
mappedMessages.push({
_id: "0",
text: 'Vous avez matché !!!',
system: true,
}); });
}, [navigation]);
setMessages(mappedMessages);
}, [conversations]);
const onSend = useCallback((messages: any = []) => {
const newMessage = new Message(
"-1",
messages[0].text,
"User1",
new Date()
);
// @ts-ignore
dispatch(sendMessage(item, newMessage));
}, [])
const renderBubble = (props: any) => {
return (
<Bubble
{...props}
wrapperStyle={{
left: {
backgroundColor: style.Card,
}
}}
textStyle={{
left: {
paddingHorizontal: 3,
color: style.Text,
},
right: {
paddingHorizontal: 3
}
}}
/>
);
};
const renderInputToolbar = (props: any) => {
return (
<InputToolbar
{...props}
containerStyle={{
backgroundColor: style.Card,
borderTopWidth: 0,
}}
primaryStyle={{
alignItems: "center"
}}
/>
);
};
function handleImageIconPress(): void {
console.log("Image");
}
function handleMicrophoneIconPress(): void {
console.log("Audio");
}
const renderActions = (props: any) => {
return (
<View style={{ flexDirection: 'row', marginLeft: 15 }}>
<TouchableOpacity onPress={handleImageIconPress}>
<FontAwesomeIcon icon={faFileImage} size={20} color={style.Line} style={{ marginRight: 10 }} />
</TouchableOpacity>
<TouchableOpacity onPress={handleMicrophoneIconPress}>
<FontAwesomeIcon icon={faMicrophone} size={20} color={style.Line} />
</TouchableOpacity>
</View>
);
};
const renderSend = (props: any) => {
return (
<Send {...props}>
<View>
<Icon name="send" size={20} style={{ marginBottom: 12, marginHorizontal: 8 }} color="#2e64e5" />
</View>
</Send>
);
};
const scrollToBottomComponent = () => {
return (
<FontAwesome name='angle-double-down' size={22} color="#333" />
)
}
return ( return (
<GiftedChat /> <SafeAreaView style={{ flex: 1, backgroundColor: style.Card }}>
) <GiftedChat
messages={messages}
onSend={messages => onSend(messages)}
user={{
_id: "User1",
}}
listViewProps={{
style: {
backgroundColor: style.body
},
}}
// @ts-ignore
textInputStyle={{
backgroundColor: style.Line,
borderRadius: 20,
paddingHorizontal: 15,
paddingTop: 10,
marginTop: 5,
color: style.Text
}}
renderActions={renderActions}
maxInputLength={255}
renderBubble={renderBubble}
renderInputToolbar={renderInputToolbar}
renderSend={renderSend}
scrollToBottom
scrollToBottomComponent={scrollToBottomComponent}
placeholder="Chat"
/>
</SafeAreaView>
);
} }

@ -1,25 +1,39 @@
import { useNavigation } from "@react-navigation/native"; import { useNavigation } from "@react-navigation/native";
import { StyleSheet, Text, View, FlatList, TouchableOpacity } from "react-native"; import { StyleSheet, Text, View, FlatList, TouchableOpacity, RefreshControl } from "react-native";
import { useSelector } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { colorsDark } from '../constants/colorsDark'; import { colorsDark } from '../constants/colorsDark';
import { colorsLight } from '../constants/colorsLight'; import { colorsLight } from '../constants/colorsLight';
import Friend from "../components/FriendComponent"; import Friend from "../components/FriendComponent";
import normalize from '../components/Normalize'; import normalize from '../components/Normalize';
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { useCallback, useEffect, useState } from "react";
import { getConversations } from "../redux/thunk/chatThunk";
export default function ConversationScreen() { export default function ConversationScreen() {
//@ts-ignore
const friends = useSelector(state => state.appReducer.conversations);
// @ts-ignore // @ts-ignore
const isDark = useSelector(state => state.userReducer.dark); const isDark = useSelector(state => state.userReducer.dark);
const [refreshing, setRefreshing] = useState(false);
const navigation = useNavigation(); const dispatch = useDispatch();
useEffect(() => {
// @ts-ignore
dispatch(getConversations());
}, []);
const handleRefresh = () => {
setRefreshing(true);
//@ts-ignore
dispatch(getConversations());
setTimeout(() => {
setRefreshing(false);
}, 700);
};
const friends = [ const navigation = useNavigation();
{ id: 1, name: "Lucas", lastMessage: "J'en ai marre de provot", source: "https://i1.sndcdn.com/artworks-ncJnbnDbNOFd-0-t500x500.jpg" },
{ id: 2, name: "Louison", lastMessage: "Tu vien piscine ?", source: "https://i1.sndcdn.com/artworks-ncJnbnDbNOFd-0-t500x500.jpg" },
{ id: 3, name: "Dave", lastMessage: "Ok c noté !", source: "https://img.lemde.fr/2019/04/05/0/0/960/960/664/0/75/0/18299d3_tUvp2AZPH_jnsIL2ypVFGUro.jpg" },
{ id: 4, name: "Valentin", lastMessage: "Haha react native c incroyable !!!", source: "https://i1.sndcdn.com/artworks-ncJnbnDbNOFd-0-t500x500.jpg" },
];
const style = isDark ? colorsDark : colorsLight; const style = isDark ? colorsDark : colorsLight;
@ -44,6 +58,18 @@ export default function ConversationScreen() {
fontSize: normalize(20), fontSize: normalize(20),
color: '#787878', color: '#787878',
marginBottom: 5 marginBottom: 5
},
body: {
alignItems: 'center',
justifyContent: 'center',
flex: 1,
marginHorizontal: "7%"
},
text: {
color: style.Text,
fontSize: normalize(18),
opacity: 0.8,
textAlign: 'center'
} }
}) })
@ -53,18 +79,33 @@ export default function ConversationScreen() {
<Text style={styles.title}>Messages</Text> <Text style={styles.title}>Messages</Text>
<Text style={styles.description}>Retrouvez ici les discussions</Text> <Text style={styles.description}>Retrouvez ici les discussions</Text>
</View> </View>
<FlatList {friends.length === 0 ? (
style={{ marginTop: 10 }} <View style={styles.body}>
data={friends} <Text style={ styles.text }>
keyExtractor={(item) => item.id.toString()} Pas de conversations pour le moment. 🥲{'\n'}
renderItem={({ item }) => ( Va liker des musiques pour créer des conversations avec des gens dans le monde ! 🔥🎆
<TouchableOpacity </Text>
</View>
) : (
<FlatList
style={{ marginTop: 10 }}
data={friends.sort((a: any, b: any) => b.lastMessage.date - a.lastMessage.date)}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
// @ts-ignore // @ts-ignore
onPress={() => navigation.navigate('Chat')}> <TouchableOpacity onPress={() => navigation.navigate('Chat', { username: item.name, image: item.image, conversation: item.id })}>
<Friend image={item.source} name={item.name} lastMessage={item.lastMessage} /> <Friend image={item.image} name={item.name} lastMessage={item.lastMessage} />
</TouchableOpacity> </TouchableOpacity>
)} )}
/> refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={style.Text}
/>
}
/>
)}
</View> </View>
) )
} }

@ -136,7 +136,7 @@ export default function FavoriteScreen() {
<Text style={styles.description}>Retrouvez ici vos musiques favorites</Text> <Text style={styles.description}>Retrouvez ici vos musiques favorites</Text>
</View> </View>
<SectionList <SectionList
style = {styles.collection} style={styles.collection}
sections={groupByDate(favoriteMusic)} sections={groupByDate(favoriteMusic)}
refreshControl={ refreshControl={
<RefreshControl <RefreshControl

@ -19,9 +19,9 @@ import { colorsLight } from '../constants/colorsLight';
export default function SpotScreen() { export default function SpotScreen() {
//@ts-ignore //@ts-ignore
const spotReducer: Spot[] = useSelector(state => state.appReducer.spot) const spotReducer: Spot[] = useSelector(state => state.appReducer.spot)
// @ts-ignore // @ts-ignore
const isDark = useSelector(state => state.userReducer.dark); const isDark = useSelector(state => state.userReducer.dark);
const style = isDark ? colorsDark : colorsLight; const style = isDark ? colorsDark : colorsLight;
const [cards, setCards] = useState<Spot[]>(spotReducer); const [cards, setCards] = useState<Spot[]>(spotReducer);
const [currentCard, setcurrentCard] = useState<Spot>(cards[cards.length - 1]); const [currentCard, setcurrentCard] = useState<Spot>(cards[cards.length - 1]);

@ -0,0 +1,8 @@
import Conversation from "../../../models/Conversation";
import Message from "../../../models/Message";
export default interface IMessageService {
getConversations(): Promise<Conversation[]>;
getMessagesWithIdConversation(id: string): Promise<Message[]>;
sendMessage(id: string, mes: Message): Promise<void>;
}

File diff suppressed because one or more lines are too long

@ -53,9 +53,11 @@ export default class SpotifyService implements IMusicService {
}, },
}); });
if (response.data.item === undefined) { if (response.data.item === undefined || response.data.item === null) {
return null; return null;
} }
return response.data.item.id return response.data.item.id
} }

Loading…
Cancel
Save