diff --git a/package.json b/package.json index d3c1af156..f0424473e 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "react-masonry-css": "1.0.16", "react-modal": "3.14.4", "react-router-dom": "5.3.0", + "react-timeago": "^8.2.0", "react-timer-hook": "3.0.5", "react-transition-group": "4.4.2", "react-virtualized": "9.22.3", diff --git a/src/background/services/firebase/models.ts b/src/background/services/firebase/models.ts index eb9634746..81e53eee2 100644 --- a/src/background/services/firebase/models.ts +++ b/src/background/services/firebase/models.ts @@ -21,4 +21,5 @@ export interface ChatConfig extends ConfigParams { export interface ChatDialogHistory { role: 'model' | 'user'; content: string; + timestamp: number; } diff --git a/src/contexts/FirebaseProvider.tsx b/src/contexts/FirebaseProvider.tsx index ca05df23a..2eac84129 100644 --- a/src/contexts/FirebaseProvider.tsx +++ b/src/contexts/FirebaseProvider.tsx @@ -19,6 +19,7 @@ import { export interface PromptItem { role: 'model' | 'user'; content: string; + timestamp: number; } const FirebaseContext = createContext<{ @@ -40,6 +41,7 @@ const FirebaseContext = createContext<{ { role: 'model' | 'user'; content: string; + timestamp: number; }[] > >; @@ -53,6 +55,7 @@ export function FirebaseContextProvider({ children }: { children: any }) { { role: 'model', content: `Hey there! I'm Core AI, here to help you manage your assets safely and smoothly. What can I do for you today?`, + timestamp: Date.now(), }, ]); diff --git a/src/pages/Home/components/Portfolio/Prompt/Prompt.tsx b/src/pages/Home/components/Portfolio/Prompt/Prompt.tsx index ae935977a..596faeed1 100644 --- a/src/pages/Home/components/Portfolio/Prompt/Prompt.tsx +++ b/src/pages/Home/components/Portfolio/Prompt/Prompt.tsx @@ -437,7 +437,10 @@ export function Prompt() { async (message: string) => { setIsTyping(true); setPrompts((prev) => { - return [...prev, { role: 'user', content: message }]; + return [ + ...prev, + { role: 'user', content: message, timestamp: Date.now() }, + ]; }); setInput(''); @@ -510,7 +513,14 @@ export function Prompt() { }); // Log the text response. setPrompts((prev) => { - return [...prev, { role: 'model', content: functionResult.text }]; + return [ + ...prev, + { + role: 'model', + content: functionResult.text, + timestamp: Date.now(), + }, + ]; }); } catch (e: any) { const errorMessage = @@ -542,7 +552,14 @@ export function Prompt() { // Log the text response. setPrompts((prev) => { - return [...prev, { role: 'model', content: errorResult.text }]; + return [ + ...prev, + { + role: 'model', + content: errorResult.text, + timestamp: Date.now(), + }, + ]; }); } } else { @@ -550,7 +567,10 @@ export function Prompt() { throw new Error('EMPTY_RESPONSE'); } setPrompts((prev) => { - return [...prev, { role: 'model', content: response.text }]; + return [ + ...prev, + { role: 'model', content: response.text, timestamp: Date.now() }, + ]; }); } } catch (e: any) { @@ -568,6 +588,7 @@ export function Prompt() { role: 'model', content: 'Whooops... There is something wrong with the service please try again later!', + timestamp: Date.now(), }, ]; }); @@ -579,6 +600,7 @@ export function Prompt() { role: 'model', content: "I'm sorry but I cannot fullfil your request at the moment. You can try again later!", + timestamp: Date.now(), }, ]; }); @@ -590,6 +612,7 @@ export function Prompt() { role: 'model', content: "Whooopsie... We've encountered some issues please try again later!", + timestamp: Date.now(), }, ]; }); diff --git a/src/pages/Home/components/Portfolio/Prompt/PromptElements.tsx b/src/pages/Home/components/Portfolio/Prompt/PromptElements.tsx index 34322e34c..100475bbd 100644 --- a/src/pages/Home/components/Portfolio/Prompt/PromptElements.tsx +++ b/src/pages/Home/components/Portfolio/Prompt/PromptElements.tsx @@ -14,6 +14,7 @@ import { useTranslation } from 'react-i18next'; import { PromptItem } from '@src/contexts/FirebaseProvider'; import { Typewriter } from './Typewriter'; import ReactMarkdown from 'react-markdown'; +import TimeAgo from 'react-timeago'; const Avatar = styled(Stack)(() => ({ position: 'relative', @@ -62,53 +63,60 @@ export const AIDialog = ({ }, [isTextTyped, isDialogOpen]); return ( - { - if (!isTextTyped) { - setIsTextTyped(true); - } - }} - > - - - - - + + + + + + { + if (!isTextTyped) { + setIsTextTyped(true); + } }} > - {!isTextTyped && ( - - - - )} - {isTextTyped && ( - - {message.content} - - )} - + + + + + + {!isTextTyped && ( + + + + )} + {isTextTyped && ( + + {message.content} + + )} + + ); }; @@ -116,22 +124,29 @@ export const AIDialog = ({ export const UserDialog = ({ message }) => { const theme = useTheme(); return ( - - {message.content} + + + + + + + + {message.content} + ); }; diff --git a/yarn.lock b/yarn.lock index badda86b3..124b270a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12747,6 +12747,7 @@ __metadata: react-router-dom: "npm:5.3.0" react-scripts: "npm:5.0.1" react-test-renderer: "npm:17.0.2" + react-timeago: "npm:^8.2.0" react-timer-hook: "npm:3.0.5" react-transition-group: "npm:4.4.2" react-virtualized: "npm:9.22.3" @@ -28853,6 +28854,15 @@ __metadata: languageName: node linkType: hard +"react-timeago@npm:^8.2.0": + version: 8.2.0 + resolution: "react-timeago@npm:8.2.0" + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10c0/6616994851f673661b9db9be5eb91086734fda32055765a30a822e7ed4c7a4871660eb772fecaa2b64be8d68fe5043d37624cfd6cdd19b40aba72180ee786e18 + languageName: node + linkType: hard + "react-timer-hook@npm:3.0.5": version: 3.0.5 resolution: "react-timer-hook@npm:3.0.5"