diff --git a/ApplicationRoot.js b/ApplicationRoot.js
index 2572a1ec..ce2acd7e 100644
--- a/ApplicationRoot.js
+++ b/ApplicationRoot.js
@@ -1,7 +1,7 @@
-import React, { useState, useCallback, useEffect} from 'react';
+import React, { useState, useCallback, useEffect } from 'react';
import { StyleSheet, View, TouchableOpacity, Linking, Platform, Animated } from 'react-native';
import AboutUsScreen from './screens/AboutUsScreen';
-import ChatSessionScreen from './screens/ChatSessionScreen';
+import HomeSearchScreen from './screens/HomeSearchScreen.js';
import ChatSessionHistoriesScreen from './screens/ChatSessionHistoriesScreen';
import MyPalettesScreen from './screens/MyPalettesScreen.js';
import Colors from './constants/Styles';
@@ -10,6 +10,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import ColorDetailsScreen from './screens/ColorDetailScreen';
import PalettesScreen from './screens/PalettesScreen';
import SavePaletteScreen from './screens/SavePaletteScreen';
+import ChatSessionScreen from './screens/ChatSessionScreen';
import ColorListScreen from './screens/ColorListScreen';
import PaletteViewScreen from './screens/PaletteViewScreen.js';
import PaletteEditScreen from './screens/PaletteEditScreen.js';
@@ -29,7 +30,7 @@ import UserProfile from './screens/UserProfileScreen.js';
import useApplicationStore from './hooks/useApplicationStore.js';
import ExplorePaletteScreen from './screens/ExplorePaletteScreen.js';
import { notifyMessage } from './libs/Helpers.js';
-import FlashMessage from "react-native-flash-message";
+import FlashMessage from 'react-native-flash-message';
import ShareMenu from 'react-native-share-menu';
import Color from 'pigment/full';
import { logEvent } from './libs/Helpers.js';
@@ -43,11 +44,11 @@ export default function App() {
const { loadInitPaletteFromStore } = applicationState;
const [isMenuOpen, setMenu] = useState(false);
const navigationRef = useNavigationContainerRef();
- useIAPConnection(function(error) {
+ useIAPConnection(function (error) {
if (error) {
// TODO: figure out a better way to handle this error and show user a way to retry, ask for help or continue.
- notifyMessage("Error during purchase initialization. Purchase might not work. Please retry");
- }
+ notifyMessage('Error during purchase initialization. Purchase might not work. Please retry');
+ }
loadInitPaletteFromStore(); // Still load the palettes. Specially simulator will always face this issue.
});
@@ -84,7 +85,7 @@ export default function App() {
});
} catch (error) {
notifyMessage('Error parsing url: ' + error.message);
- navigationRef.navigate(ROUTE_NAMES.HOME);
+ navigationRef.navigate(ROUTE_NAMES.HOME_SEARCH);
}
},
[navigationRef]
@@ -165,12 +166,22 @@ export default function App() {
height: HEADER_HEIGHT
}
}}>
+
{
return {
headerLeft: hamburgerMenuIcon,
- headerTitleContainerStyle: { left: 40 },
+ headerTitleContainerStyle: { left: 40 },
title: t('My Palettes')
};
}}
@@ -189,7 +200,7 @@ export default function App() {
options={{ title: t('About us') }}
component={AboutUsScreen}
/>
-
+
-
+
);
@@ -248,7 +259,7 @@ const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
- flexDirection: 'row',
+ flexDirection: 'row'
},
sideMenuIcon: {
fontSize: 25,
diff --git a/components/GridActionButton.js b/components/GridActionButton.js
index fb9a8108..732ba513 100644
--- a/components/GridActionButton.js
+++ b/components/GridActionButton.js
@@ -8,7 +8,7 @@ import {
Text,
Image,
TouchableOpacity,
- Platform,
+ Platform
} from 'react-native';
import Color from 'pigment/full';
import RNColorThief from 'react-native-color-thief';
@@ -30,8 +30,7 @@ import useApplicationStore from '../hooks/useApplicationStore';
import MultiColorView from './MultiColorView';
import { ROUTE_NAMES } from '../libs/constants';
-
-const GridActionButton = ({ navigation}) => {
+const GridActionButton = ({ navigation }) => {
const { t } = useTranslation();
const [pickImageLoading, setPickImageLoading] = useState(false);
const [isColorPickerVisible, setIsColorPickerVisible] = React.useState(false);
@@ -174,38 +173,38 @@ const GridActionButton = ({ navigation}) => {
logEvent('chat_session_action_button');
props.navigation.reset({
index: 0,
- routes: [{ name: ROUTE_NAMES.CHAT_SESSION }],
+ routes: [{ name: ROUTE_NAMES.HOME_SEARCH }]
});
}
},
- Platform.OS == 'android' ? (
- pro.plan !== 'starter'
- ? {
- id: 6,
- icon: ,
- text1: t('Create palette'),
- text2: t(' manually'),
- onPress: () => {
- logEvent('create_new_palette');
- navigation.navigate('SavePalette');
+ Platform.OS == 'android'
+ ? pro.plan !== 'starter'
+ ? {
+ id: 6,
+ icon: ,
+ text1: t('Create palette'),
+ text2: t(' manually'),
+ onPress: () => {
+ logEvent('create_new_palette');
+ navigation.navigate('SavePalette');
+ }
}
- }
- : {
- id: 7,
- icon: ,
- text1: t('Unlock'),
- text2: t('Pro'),
- onPress: () => {
- logEvent('home_screen_pro_button');
- navigation.navigate('ProVersion');
+ : {
+ id: 7,
+ icon: ,
+ text1: t('Unlock'),
+ text2: t('Pro'),
+ onPress: () => {
+ logEvent('home_screen_pro_button');
+ navigation.navigate('ProVersion');
+ }
}
- }) : null
+ : null
].filter(Boolean)
];
return (
<>
-
+
{
setSelectedImage(null);
setAutomaticColors([]);
}}>
- {pickImageLoading &&
-
- }
+ {pickImageLoading && (
+
+ )}
{
setIsImagePickerModalVisible(false);
@@ -256,22 +255,23 @@ const GridActionButton = ({ navigation}) => {
{t('Next')}
- {Platform.OS == 'android' && (<>
-
- {t('OR')}
-
-
-
- {t('Pick colors Manually')}
-
- >
+ {Platform.OS == 'android' && (
+ <>
+
+
+ {t('OR')}
+
+
+
+ {t('Pick colors Manually')}
+
+ >
)}
-
@@ -319,7 +319,7 @@ const styles = {
height: 120
},
imageExtractedColorPreview: {
- margin: 16,
+ margin: 16
},
colorPickerModalContent: {
backgroundColor: 'white',
@@ -333,7 +333,7 @@ const styles = {
previewImage: {
height: 150,
resizeMode: 'contain',
- marginHorizontal: 20,
+ marginHorizontal: 20
},
colorPreviewContainer: {
display: 'flex',
@@ -349,7 +349,7 @@ const styles = {
},
pickColorsButton: {
alignItems: 'center',
- marginVertical: 8,
+ marginVertical: 8
},
pickColorsButtonText: {
fontSize: 18,
diff --git a/components/HamburgerMenu.js b/components/HamburgerMenu.js
index be94b2c3..20079c7a 100644
--- a/components/HamburgerMenu.js
+++ b/components/HamburgerMenu.js
@@ -57,14 +57,14 @@ const HamburgerMenu = (props) => {
- {
logEvent('home');
props.toggleSideMenu();
props.navigation.reset({
index: 0,
- routes: [{ name: ROUTE_NAMES.HOME }],
+ routes: [{ name: ROUTE_NAMES.HOME_SEARCH }]
});
}}>
@@ -100,20 +100,21 @@ const HamburgerMenu = (props) => {
{t('Explore Palettes')}
- {Platform.OS == 'ios' && {
- logEvent('hm_palette_library');
- navigate('PaletteLibrary');
- }}>
-
-
-
+ {Platform.OS == 'ios' && (
+ {
+ logEvent('hm_palette_library');
+ navigate('PaletteLibrary');
+ }}>
+
+
+
+
+ {t('Palette Library')}
- {t('Palette Library')}
-
-
- }
+
+ )}
{
{
: 'https://apps.apple.com/app/id1596763657?action=write-review'
}
icon={}>
- {t('Rate us on ' + (Platform.OS == 'android' ? 'PlayStore' : "AppStore"))}
+ {t('Rate us on ' + (Platform.OS == 'android' ? 'PlayStore' : 'AppStore'))}
}
{
{t('About us')}
- { Platform.OS == 'android' && // right now histories requires login. That's why enabling it in only android.
+ {Platform.OS == 'android' && ( // right now histories requires login. That's why enabling it in only android.
{
@@ -166,8 +167,8 @@ const HamburgerMenu = (props) => {
{t('Huehive AI chat history')}
- }
- {(Platform.OS == 'android' && !userData) && (
+ )}
+ {Platform.OS == 'android' && !userData && (
{
@@ -183,7 +184,7 @@ const HamburgerMenu = (props) => {
)}
- {(Platform.OS == 'android') && (
+ {Platform.OS == 'android' && (
{
diff --git a/hooks/useChatSession.js b/hooks/useChatSession.js
index 17685aec..e0dc79cf 100644
--- a/hooks/useChatSession.js
+++ b/hooks/useChatSession.js
@@ -12,14 +12,16 @@ const useChatSession = (initialMessages) => {
const interval = setInterval(async () => {
try {
const messageResponse = await getChatSession(chatSession.data.id, latestMessage.id);
+ console.log('Test it ', latestMessage.id);
if (messageResponse.data.length > 0) {
+ console.log(messageResponse.data);
clearInterval(interval);
setMessages((prevMessages) => [...prevMessages, ...messageResponse.data]);
setIsLoading(false);
}
} catch (error) {
console.error('Error fetching chat session updates', error);
- setError(error);
+ setError(error.toString());
sendClientError('fetch_new_message', error.message);
clearInterval(interval);
}
@@ -38,7 +40,7 @@ const useChatSession = (initialMessages) => {
return chatSession;
} catch (error) {
console.error('Error creating chat session', error);
- setError(error);
+ setError(error.toString());
sendClientError('create_session', error.message);
throw error;
} finally {
diff --git a/libs/constants.js b/libs/constants.js
index 342e36b8..92bb8da5 100644
--- a/libs/constants.js
+++ b/libs/constants.js
@@ -1,7 +1,7 @@
export const ROUTE_NAMES = {
MY_PALETTES: 'MyPalettes',
- HOME: 'ChatSession',
ABOUT_US: 'AboutUs',
+ HOME_SEARCH: 'HomeSearch',
CHAT_SESSION: 'ChatSession',
CHAT_SESSION_HISTORIES: 'ChatSessionHistories',
COLOR_DETAILS: 'ColorDetails',
@@ -16,6 +16,6 @@ export const ROUTE_NAMES = {
export const NUMBER_OF_COLORS_PRO_COUNT = 10;
export const PRIVATE_ROUTES = new Set([
- ROUTE_NAMES.CHAT_SESSION,
+ ROUTE_NAMES.HOME_SEARCH,
ROUTE_NAMES.CHAT_SESSION_HISTORIES
]);
diff --git a/screens/ChatSessionScreen.js b/screens/ChatSessionScreen.js
index ecc9df0d..4b7d43fd 100644
--- a/screens/ChatSessionScreen.js
+++ b/screens/ChatSessionScreen.js
@@ -7,9 +7,9 @@ import {
TextInput,
ActivityIndicator,
Text,
- ImageBackground,
- Platform,
+ 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';
@@ -18,8 +18,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');
@@ -32,16 +30,17 @@ const ChatSessionScreen = (props) => {
useChatSession(route.params?.messages);
useEffect(() => {
- logEvent('chat_session_screen');
+ logEvent('chat_session_follow_up_screen');
+ handleSendMessage(route.params.userQuery);
}, []);
- const handleSendMessage = async () => {
+ const handleSendMessage = async (userQuery) => {
const message = {
chat_session: {
chat_session_type: 'color_palette',
messages_attributes: [
{
- message: inputText,
+ message: userQuery || inputText,
sender_type: 'user'
}
]
@@ -58,13 +57,6 @@ const ChatSessionScreen = (props) => {
scrollViewRef.current.scrollToEnd({ animated: true });
};
- useEffect(() => {
- let interval;
- return () => {
- clearInterval(interval);
- };
- }, [messages]);
-
function showUnlockPro() {
return pro.plan === 'starter' && messages.length >= 2;
}
@@ -84,42 +76,15 @@ const ChatSessionScreen = (props) => {
ref={scrollViewRef}
style={styles.chat_container}
showsVerticalScrollIndicator={false}>
- {messages.length === 0 ? (
-
-
- Welcome to HueHive AI!
-
-
- Start by generating a color palette for your next project.
-
-
-
-
- Generate
-
-
-
- ) : (
- messages.map((message, index) => (
-
- ))
- )}
+ {messages.map((message, index) => (
+
+ ))}
+
{error && (
@@ -128,9 +93,9 @@ const ChatSessionScreen = (props) => {
{error}
)}
-
-
- {!showUnlockPro() && messages.length > 0 && (
+
+ {/* {!showUnlockPro() && messages.length > 0 && ( */}
+ {true && (
{
/>
{
+ handleSendMessage();
+ }}
style={
- isLoading || inputText.trim() === '' ? styles.disableSendButton : styles.sendButton
+ isLoading || inputText.trim() === ''
+ ? styles.disableSendButton
+ : styles.sendButton
}>
Send
)}
-
+
{showUnlockPro() && (
{
)}
>
)}
-
- { messages.length < 2 && Platform.OS == 'android' && }
-
-
);
};
@@ -209,33 +174,46 @@ const styles = StyleSheet.create({
marginBottom: 20
},
searchInputContainer: {
- flexDirection: 'row',
+ flexDirection: 'column',
alignItems: 'center',
- justifyContent: 'center'
+ justifyContent: 'center',
+ width: '100%',
+ gap: 15,
+ marginTop: 10
},
input: {
- flex: 1,
- marginRight: 12,
- paddingVertical: 8,
- paddingHorizontal: 12,
borderWidth: 1,
borderColor: 'gray',
borderRadius: 8,
- height: 40
+ flex: 1,
+ height: 40,
+ fontSize: 16
},
generateButton: {
- padding: 8,
+ padding: 10,
+ paddingLeft: 25,
+ paddingRight: 25,
backgroundColor: Colors.primary,
- borderRadius: 8
+ borderRadius: 8,
+ display: 'flex',
+ flexDirection: 'row',
+ gap: 5,
+ alignItems: 'center'
},
disableGenerateButton: {
- padding: 8,
+ padding: 7,
+ paddingLeft: 25,
+ paddingRight: 25,
backgroundColor: 'gray',
- borderRadius: 8
+ borderRadius: 8,
+ display: 'flex',
+ flexDirection: 'row',
+ gap: 5,
+ alignItems: 'center'
},
textGenerate: {
color: 'white',
- fontSize: 16,
+ fontSize: 20,
fontWeight: 'bold',
textAlign: 'center'
},
diff --git a/screens/HomeSearchScreen.js b/screens/HomeSearchScreen.js
new file mode 100644
index 00000000..a25226dd
--- /dev/null
+++ b/screens/HomeSearchScreen.js
@@ -0,0 +1,160 @@
+import {
+ ScrollView,
+ StyleSheet,
+ TouchableOpacity,
+ View,
+ TextInput,
+ 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';
+import { logEvent } from '../libs/Helpers';
+import useApplicationStore from '../hooks/useApplicationStore';
+import GridActionButton from '../components/GridActionButton';
+import AdBanner from '../components/AdBanner';
+
+const bgImage = require('../assets/images/colorful_background.jpg');
+
+const ChatSessionScreen = (props) => {
+ const { navigation } = props;
+ const [userQuery, setUserQuery] = useState('');
+ const scrollViewRef = useRef();
+ const { pro } = useApplicationStore();
+
+ useEffect(() => {
+ logEvent('chat_session_follow_up_screen');
+ }, []);
+
+ return (
+
+
+
+
+
+ Welcome to HueHive AI!
+
+ Create a color palette using AI or explore various methods to extract a color
+ palette.
+
+
+
+ {
+ navigation.navigate('ChatSession', { userQuery: userQuery });
+ }}
+ style={
+ userQuery.trim() === '' ? styles.disableGenerateButton : styles.generateButton
+ }>
+ Generate
+
+
+
+
+
+ {Platform.OS == 'android' && }
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ display: 'flex',
+ flexDirection: 'column',
+ backgroundColor: '#d6e4ff',
+ flex: 1
+ },
+ chat_container: {
+ flex: 1,
+ padding: 5
+ },
+ backgroundImage: {
+ flex: 1,
+ resizeMode: 'cover',
+ justifyContent: 'center'
+ },
+ bgImageOpecity: {
+ backgroundColor: 'rgba(255, 255, 255, 0.6)',
+ flex: 1
+ },
+ searchContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 20
+ },
+ searchTitle: {
+ ...material.headline,
+ textAlign: 'center',
+ marginBottom: 10
+ },
+ searchSubtitle: {
+ ...material.body1,
+ textAlign: 'center',
+ marginBottom: 20
+ },
+ searchInputContainer: {
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: '100%',
+ gap: 15,
+ marginTop: 10
+ },
+ input: {
+ borderWidth: 1,
+ borderColor: 'gray',
+ borderRadius: 8,
+ width: '100%',
+ height: 40,
+ fontSize: 16
+ },
+ generateButton: {
+ padding: 10,
+ paddingLeft: 25,
+ paddingRight: 25,
+ backgroundColor: Colors.primary,
+ borderRadius: 8,
+ display: 'flex',
+ flexDirection: 'row',
+ gap: 5,
+ alignItems: 'center'
+ },
+ disableGenerateButton: {
+ padding: 7,
+ paddingLeft: 25,
+ paddingRight: 25,
+ backgroundColor: 'gray',
+ borderRadius: 8,
+ display: 'flex',
+ flexDirection: 'row',
+ gap: 5,
+ alignItems: 'center'
+ },
+ textGenerate: {
+ color: 'white',
+ fontSize: 20,
+ fontWeight: 'bold',
+ textAlign: 'center'
+ }
+});
+
+export default ChatSessionScreen;
diff --git a/screens/UserProfileScreen.js b/screens/UserProfileScreen.js
index c8ced28c..ce210e50 100644
--- a/screens/UserProfileScreen.js
+++ b/screens/UserProfileScreen.js
@@ -27,7 +27,7 @@ function UserProfile(props) {
}, []);
const { t } = useTranslation();
-
+
useEffect(() => {
GoogleSignin.configure({
webClientId: '865618605576-j2tb9toevqc7tonmbp01dim1ddvod7r0.apps.googleusercontent.com',
@@ -40,7 +40,7 @@ function UserProfile(props) {
const consentInfo = await AdsConsent.requestInfoUpdate();
setConsentInfo(consentInfo);
}
-
+
fetchConsentStatus();
}, []);
@@ -62,7 +62,7 @@ function UserProfile(props) {
await removeUserSession();
await loadUserData();
reloadPalettes();
- props.navigation.navigate(ROUTE_NAMES.HOME);
+ props.navigation.navigate(ROUTE_NAMES.HOME_SEARCH);
try {
await GoogleSignin.revokeAccess();
} catch (error) {
@@ -72,7 +72,7 @@ function UserProfile(props) {
return (
- {userData &&
+ {userData && (
@@ -90,9 +90,9 @@ function UserProfile(props) {
{t('Logout')}
- }
-
- {!userData &&
+ )}
+
+ {!userData && (
{t('Sign In / Sign Up')}
- }
+ )}
- { consentInfo.status == 'REQUIRED' &&
-
-
- {consentInfo.canRequestAds ? t('Withdraw Ad Consent') : t('Give Ad Consent')}
-
-
- }
+ {consentInfo.status == 'REQUIRED' && (
+
+
+ {consentInfo.canRequestAds ? t('Withdraw Ad Consent') : t('Give Ad Consent')}
+
+
+ )}
);
}