Skip to content

Commit

Permalink
Chat session issues (#263)
Browse files Browse the repository at this point in the history
* Fixed error session screen

* Error converted to string

* fix some minor issues

* Fixed chatSession issue

* Extracting chat session colors from backend

* Added chat screen

---------

Co-authored-by: Kamal Joshi <kkjoshi.it@gmail.com>
  • Loading branch information
bhujoshi and kamalkishor1991 authored Nov 24, 2024
1 parent 0f88c05 commit ebe5cff
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 119 deletions.
11 changes: 5 additions & 6 deletions components/ChatCard.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/* eslint-disable react/prop-types */
import React from 'react';
import { View, Text, Image } from 'react-native';
import { extractHexColors } from '../libs/Helpers';
import { PalettePreviewCard } from './PalettePreviewCard';

const ChatCard = ({ sender, message, navigation }) => {
const palette = extractHexColors(message);
const colors = palette.colors;
const paletteName = palette.name;
const ChatCard = ({ sender, message, navigation, colors, paletteName }) => {
const tokens = message.split(/(```[\s\S]+?```)|(\n)/g);

return (
Expand Down Expand Up @@ -58,7 +54,10 @@ const ChatCard = ({ sender, message, navigation }) => {
navigation.navigate('ColorList', { colors, suggestedName: paletteName });
}}
name={paletteName || ''}
colors={colors}
colors={colors.map((color) => {
color.color = color.hex;
return color;
})}
/>
</View>
);
Expand Down
25 changes: 12 additions & 13 deletions hooks/useChatSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ const useChatSession = (initialMessages) => {
const [isCreatingSession, setIsCreatingSession] = useState(false);
const [error, setError] = useState();

const fetchNewMessages = async (chatSession, latestMessage) => {
const fetchNewMessages = async (chatSessionId, latestMessage) => {
const interval = setInterval(async () => {
try {
const messageResponse = await getChatSession(chatSession.data.id, latestMessage.id);
const messageResponse = await getChatSession(chatSessionId, latestMessage.id);
if (messageResponse.data.length > 0) {
clearInterval(interval);
setMessages((prevMessages) => [...prevMessages, ...messageResponse.data]);
setIsLoading(false);
}
} catch (error) {
console.error('Error fetching chat session updates', error);
setError(error);
sendClientError('fetch_new_message', error.message);
setError(error.toString());
sendClientError('fetch_new_message', error.toString());
clearInterval(interval);
}
}, 2000);
Expand All @@ -34,12 +34,12 @@ const useChatSession = (initialMessages) => {
const chatSession = await createChatSession(message);
const latestMessage = chatSession.data.messages[chatSession.data.messages.length - 1];
setMessages([...messages, latestMessage]);
await fetchNewMessages(chatSession, latestMessage);
await fetchNewMessages(chatSession.data.id, latestMessage);
return chatSession;
} catch (error) {
console.error('Error creating chat session', error);
setError(error);
sendClientError('create_session', error.message);
setError(error.toString());
sendClientError('create_session', error.toString());
throw error;
} finally {
setIsCreatingSession(false);
Expand All @@ -51,15 +51,14 @@ const useChatSession = (initialMessages) => {
setError(null);

try {
const chatSession = await followUpChatSession(sessionId, message);
const latestMessage = chatSession.data.messages[chatSession.data.messages.length - 1];
const chatSessionRes = await followUpChatSession(sessionId, message);
const latestMessage = chatSessionRes.data;
setMessages((prevMessages) => [...prevMessages, latestMessage]);
await fetchNewMessages(chatSession, latestMessage);
return chatSession;
await fetchNewMessages(sessionId, latestMessage);
} catch (error) {
console.error('Error following up chat session', error);
setError(error);
sendClientError('followUpSession', error.message);
setError(error.toString());
sendClientError('followUpSession', error.toString());
throw error;
} finally {
setIsLoading(false);
Expand Down
78 changes: 14 additions & 64 deletions libs/Helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { NativeModules, Platform, Alert, ToastAndroid } from 'react-native';
import * as RNIap from 'react-native-iap';
import { requestPurchase, getProducts } from 'react-native-iap';
import { sendClientErrorAsync } from '../network/errors';
import { showMessage } from "react-native-flash-message";

import { showMessage } from 'react-native-flash-message';

const isProduction = () => {
// eslint-disable-next-line no-undef
Expand Down Expand Up @@ -65,15 +64,20 @@ const purchase = async function (setPurchase, currentPlan, toPlan) {
try {
const productSKU = planToSKUMapping[currentPlan][toPlan];
if (!productSKU) {
throw new Error(`Product SKU is not defined for currentPlan: ${currentPlan} and toPlan: ${toPlan}`);
throw new Error(
`Product SKU is not defined for currentPlan: ${currentPlan} and toPlan: ${toPlan}`
);
}
await getProducts({ skus: [productSKU] });
const requestPurchaseParam = Platform.OS == 'android' ? {
skus: [productSKU],
} : {
sku: productSKU,
andDangerouslyFinishTransactionAutomaticallyIOS: true
};
const requestPurchaseParam =
Platform.OS == 'android'
? {
skus: [productSKU]
}
: {
sku: productSKU,
andDangerouslyFinishTransactionAutomaticallyIOS: true
};
await requestPurchase(requestPurchaseParam);
await setPurchase(toPlan);
logEvent('purchase_successful');
Expand All @@ -86,7 +90,7 @@ const purchase = async function (setPurchase, currentPlan, toPlan) {
notifyMessage('Purchase cancelled ');
} else {
console.warn(err.code, err.message);
notifyError(`Purchase unsuccessful ${err.message}, Tap to dismiss`, {autoHide: false});
notifyError(`Purchase unsuccessful ${err.message}, Tap to dismiss`, { autoHide: false });
logEvent('purchase_failed', err.message);
sendClientError('purchase_failed', err.message + 'Error code: ' + err.code, err.stack);
}
Expand Down Expand Up @@ -194,59 +198,6 @@ function notifyError(msg) {
});
}


function extractHexColors1(text) {
let hexColors = [];
let regex = /([1-9]{1,}\. ([A-Z a-z]*?))?([ \-\(])*#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/g;
let matches = text.matchAll(regex);
let hexSet = new Set();
for (let match of matches) {
let hex = '#' + match[4];
if (!hexSet.has(hex)) {
hexSet.add(hex);
let colorName = match[2]?.trim();
hexColors.push({ color: hex, name: colorName });
}
}
return hexColors;
}

function extractHexColors2(text) {
let hexColors = [];
let regex = /Color Name:\s+(.+?)\s+Hex Code:\s+#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/g;
let matches = text.matchAll(regex);
let hexSet = new Set();
for (let match of matches) {
let hex = '#' + match[1];
if (!hexSet.has(hex)) {
hexSet.add(hex);
let colorName = match[0]?.trim();
hexColors.push({ color: hex, name: colorName });
}
}
return hexColors;
}

function extractHexColors(text) {
let extractedColors1 = extractHexColors1(text);
let extractedColors2 = extractHexColors2(text);
let combinedHexMap = {};
for (let color of extractedColors1) {
let hex = color.color;
combinedHexMap[hex] = color;
}
for (let color of extractedColors2) {
let hex = color.color;
if (hex in combinedHexMap) {
combinedHexMap[hex].name = combinedHexMap[hex].name || color.name;
} else {
combinedHexMap[hex] = color;
}
}
const match = text.match(/<\s*(.*?)\s*>/);
return { colors: Object.values(combinedHexMap), name: match ? match[1] : null };
}

function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
Expand All @@ -261,6 +212,5 @@ export {
readRemoteConfig,
planLabels,
getPlanPrice,
extractHexColors,
capitalizeFirstLetter
};
8 changes: 4 additions & 4 deletions network/chat_session.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import axiosInstance from './axios.client';

export const createChatSession = async (chatSession) => {
return axiosInstance.post('chat_sessions.json', chatSession);
export const createChatSession = async (message) => {
return axiosInstance.post('chat_sessions.json', message);
};

export const getChatSession = async (chatSessionId, lastMessageId) => {
Expand All @@ -10,8 +10,8 @@ export const getChatSession = async (chatSessionId, lastMessageId) => {
);
};

export const followUpChatSession = async (id, chatSession) => {
return axiosInstance.patch(`chat_sessions/${id}.json`, chatSession);
export const followUpChatSession = async (id, message) => {
return axiosInstance.post(`chat_sessions/${id}/messages`, message);
};

export const getChatSessions = async () => {
Expand Down
52 changes: 24 additions & 28 deletions screens/ChatSessionScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
Text,
ImageBackground
} from 'react-native';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import Colors from '../constants/Styles';
import React, { useState, useEffect, useRef } from 'react';
import { material } from 'react-native-typography';
Expand All @@ -18,8 +17,6 @@ import ChatCard from '../components/ChatCard';
import CromaButton from '../components/CromaButton';
import useChatSession from '../hooks/useChatSession';
import useApplicationStore from '../hooks/useApplicationStore';
import GridActionButton from '../components/GridActionButton';
import AdBanner from '../components/AdBanner'; // Import the new AdBanner component

const bgImage = require('../assets/images/colorful_background.jpg');

Expand All @@ -33,32 +30,28 @@ const ChatSessionScreen = (props) => {

useEffect(() => {
logEvent('chat_session_follow_up_screen');
handleSendMessage(route.params.userQuery);
if (route.params.userQuery) {
logEvent('chat_session_create');
const message = {
chat_session: {
chat_session_type: 'color_palette',
messages_attributes: [
{
message: route.params.userQuery,
sender_type: 'user'
}
]
}
};
createSession(message);
}
}, []);

onTextChange = (text) => {
setInputText(text.match(/.{1,30}/g).join('\n'));
};

const handleSendMessage = async (userQuery) => {
const followUpQuery = async (userQuery) => {
const message = {
chat_session: {
chat_session_type: 'color_palette',
messages_attributes: [
{
message: userQuery || inputText,
sender_type: 'user'
}
]
}
message: userQuery
};
if (messages.length === 0) {
logEvent('chat_session_create');
await createSession(message);
} else {
logEvent('chat_session_follow_up');
await followUpSession(messages[0].chat_session_id, message);
}
await followUpSession(messages[0].chat_session_id, { message });
setInputText('');
scrollViewRef.current.scrollToEnd({ animated: true });
};
Expand Down Expand Up @@ -86,8 +79,9 @@ const ChatSessionScreen = (props) => {
<ChatCard
sender={message.sender_type}
message={message.message}
key={message.id}
colors={message?.ai_generated_palette?.colors}
index={index}
paletteName={message?.ai_generated_palette?.name}
navigation={navigation}
/>
))}
Expand All @@ -111,7 +105,9 @@ const ChatSessionScreen = (props) => {
/>
<TouchableOpacity
disabled={isLoading || inputText.trim() === ''}
onPress={handleSendMessage}
onPress={() => {
followUpQuery(inputText);
}}
style={
isLoading || inputText.trim() === ''
? styles.disableSendButton
Expand Down Expand Up @@ -189,7 +185,7 @@ const styles = StyleSheet.create({
borderWidth: 1,
borderColor: 'gray',
borderRadius: 8,
width: '100%',
flex: 1,
height: 40,
fontSize: 16
},
Expand Down
4 changes: 0 additions & 4 deletions screens/HomeSearchScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ const ChatSessionScreen = (props) => {
logEvent('chat_session_follow_up_screen');
}, []);

onTextChange = (text) => {
setUserQuery(text.match(/.{1,30}/g).join('\n'));
};

return (
<View style={styles.container}>
<ImageBackground source={bgImage} style={styles.backgroundImage}>
Expand Down

0 comments on commit ebe5cff

Please sign in to comment.