mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
feat: main styling/ui/ux final changes
This commit is contained in:
parent
67161c983f
commit
8f58c95452
17 changed files with 166 additions and 70 deletions
|
|
@ -16,7 +16,7 @@ async function indexSync(req, res, next) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { status } = await client.health();
|
const { status } = await client.health();
|
||||||
console.log(`Meilisearch: ${status}`);
|
// console.log(`Meilisearch: ${status}`);
|
||||||
const result = status === 'available' && !!process.env.SEARCH;
|
const result = status === 'available' && !!process.env.SEARCH;
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cache = {};
|
const cache = {};
|
||||||
|
const convoMap = {};
|
||||||
const promises = [];
|
const promises = [];
|
||||||
// will handle a syncing solution soon
|
// will handle a syncing solution soon
|
||||||
const deletedConvoIds = [];
|
const deletedConvoIds = [];
|
||||||
|
|
@ -104,6 +105,7 @@ module.exports = {
|
||||||
cache[page] = [];
|
cache[page] = [];
|
||||||
}
|
}
|
||||||
cache[page].push(convo);
|
cache[page].push(convo);
|
||||||
|
convoMap[convo.conversationId] = convo;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -120,7 +122,8 @@ module.exports = {
|
||||||
pageNumber,
|
pageNumber,
|
||||||
pageSize,
|
pageSize,
|
||||||
// will handle a syncing solution soon
|
// will handle a syncing solution soon
|
||||||
filter: new Set(deletedConvoIds)
|
filter: new Set(deletedConvoIds),
|
||||||
|
convoMap
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ const { MeiliSearch } = require('meilisearch');
|
||||||
const { Message } = require('../../models/Message');
|
const { Message } = require('../../models/Message');
|
||||||
const { Conversation, getConvosQueried } = require('../../models/Conversation');
|
const { Conversation, getConvosQueried } = require('../../models/Conversation');
|
||||||
const { reduceHits } = require('../../lib/utils/reduceHits');
|
const { reduceHits } = require('../../lib/utils/reduceHits');
|
||||||
|
const { cleanUpPrimaryKeyValue } = require('../../lib/utils/misc');
|
||||||
const cache = new Map();
|
const cache = new Map();
|
||||||
|
|
||||||
router.get('/sync', async function (req, res) {
|
router.get('/sync', async function (req, res) {
|
||||||
|
|
@ -52,9 +53,25 @@ router.get('/', async function (req, res) {
|
||||||
console.log('messages', messages.length, 'titles', titles.length);
|
console.log('messages', messages.length, 'titles', titles.length);
|
||||||
const sortedHits = reduceHits(messages, titles);
|
const sortedHits = reduceHits(messages, titles);
|
||||||
const result = await getConvosQueried(user, sortedHits, pageNumber);
|
const result = await getConvosQueried(user, sortedHits, pageNumber);
|
||||||
cache.set(q, result.cache);
|
cache.set(key, result.cache);
|
||||||
delete result.cache;
|
delete result.cache;
|
||||||
result.messages = messages.filter(message => !result.filter.has(message.conversationId));
|
// result.messages = messages.filter(message => { });
|
||||||
|
// !result.filter.has(message.conversationId)
|
||||||
|
|
||||||
|
const activeMessages = [];
|
||||||
|
for (let i = 0; i < messages.length; i++) {
|
||||||
|
let message = messages[i];
|
||||||
|
if (message.conversationId.includes('--')) {
|
||||||
|
message.conversationId = cleanUpPrimaryKeyValue(message.conversationId);
|
||||||
|
}
|
||||||
|
if (result.convoMap[message.conversationId] && !message.error) {
|
||||||
|
message = { ...message, title: result.convoMap[message.conversationId].title };
|
||||||
|
activeMessages.push(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.messages = activeMessages;
|
||||||
|
delete result.cache;
|
||||||
|
delete result.convoMap;
|
||||||
// for debugging
|
// for debugging
|
||||||
// console.log(result, messages.length);
|
// console.log(result, messages.length);
|
||||||
res.status(200).send(result);
|
res.status(200).send(result);
|
||||||
|
|
@ -89,7 +106,7 @@ router.get('/enable', async function (req, res) {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { status } = await client.health();
|
const { status } = await client.health();
|
||||||
console.log(`Meilisearch: ${status}`);
|
// console.log(`Meilisearch: ${status}`);
|
||||||
result = status === 'available' && !!process.env.SEARCH;
|
result = status === 'available' && !!process.env.SEARCH;
|
||||||
return res.send(result);
|
return res.send(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -350,7 +350,7 @@ export default function TextChat({ messages }) {
|
||||||
const isSearchView = messages?.[0]?.searchResult === true;
|
const isSearchView = messages?.[0]?.searchResult === true;
|
||||||
const getPlaceholderText = () => {
|
const getPlaceholderText = () => {
|
||||||
if (isSearchView) {
|
if (isSearchView) {
|
||||||
return 'Click a message to open its conversation.'
|
return 'Click a message title to open its conversation.'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ const code = React.memo((props) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const p = React.memo((props) => {
|
const p = React.memo((props) => {
|
||||||
return <p className="whitespace-pre-wrap ">{props?.children}</p>;
|
return <span className="whitespace-pre-wrap mb-2">{props?.children}</span>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const blinker = ({ node }) => {
|
const blinker = ({ node }) => {
|
||||||
|
|
|
||||||
9
client/src/components/Messages/Content/SubRow.jsx
Normal file
9
client/src/components/Messages/Content/SubRow.jsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function SubRow({ children, classes = '', subclasses = '', onClick }) {
|
||||||
|
return (
|
||||||
|
<div className={`flex justify-between ${classes}`} onClick={onClick}>
|
||||||
|
<div className={`flex items-center justify-center gap-1 self-center pt-2 text-xs ${subclasses}`}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -3,14 +3,14 @@ import TextWrapper from './TextWrapper';
|
||||||
import Content from './Content';
|
import Content from './Content';
|
||||||
|
|
||||||
const Wrapper = React.memo(({ text, generateCursor, isCreatedByUser, searchResult }) => {
|
const Wrapper = React.memo(({ text, generateCursor, isCreatedByUser, searchResult }) => {
|
||||||
if (!isCreatedByUser && searchResult) {
|
if (searchResult) {
|
||||||
return (
|
return (
|
||||||
<Content
|
<Content
|
||||||
content={text}
|
content={text}
|
||||||
generateCursor={generateCursor}
|
generateCursor={generateCursor}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else if (!isCreatedByUser && !searchResult) {
|
} else if (!isCreatedByUser) {
|
||||||
return (
|
return (
|
||||||
<TextWrapper
|
<TextWrapper
|
||||||
text={text}
|
text={text}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
import SubRow from './Content/SubRow';
|
||||||
import Wrapper from './Content/Wrapper';
|
import Wrapper from './Content/Wrapper';
|
||||||
import MultiMessage from './MultiMessage';
|
import MultiMessage from './MultiMessage';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import HoverButtons from './HoverButtons';
|
import HoverButtons from './HoverButtons';
|
||||||
import SiblingSwitch from './SiblingSwitch';
|
import SiblingSwitch from './SiblingSwitch';
|
||||||
import { setConversation, setLatestMessage } from '~/store/convoSlice';
|
import { setConversation, setLatestMessage } from '~/store/convoSlice';
|
||||||
import { setModel, setCustomModel, setCustomGpt, toggleCursor, setDisabled } from '~/store/submitSlice';
|
import { setModel, setCustomModel, setCustomGpt, setDisabled } from '~/store/submitSlice';
|
||||||
import { setMessages } from '~/store/messageSlice';
|
import { setMessages } from '~/store/messageSlice';
|
||||||
import { fetchById } from '~/utils/fetchers';
|
import { fetchById } from '~/utils/fetchers';
|
||||||
import { getIconOfModel } from '~/utils';
|
import { getIconOfModel } from '~/utils';
|
||||||
|
|
@ -21,17 +22,15 @@ export default function Message({
|
||||||
siblingCount,
|
siblingCount,
|
||||||
setSiblingIdx
|
setSiblingIdx
|
||||||
}) {
|
}) {
|
||||||
const { isSubmitting, model, chatGptLabel, cursor, promptPrefix } = useSelector(
|
const { isSubmitting, model, chatGptLabel, cursor, promptPrefix } = useSelector(state => state.submit);
|
||||||
(state) => state.submit
|
|
||||||
);
|
|
||||||
const [abortScroll, setAbort] = useState(false);
|
const [abortScroll, setAbort] = useState(false);
|
||||||
const { sender, text, searchResult, isCreatedByUser, error, submitting } = message;
|
const { sender, text, searchResult, isCreatedByUser, error, submitting } = message;
|
||||||
const textEditor = useRef(null);
|
const textEditor = useRef(null);
|
||||||
// const { convos } = useSelector((state) => state.convo);
|
|
||||||
const last = !message?.children?.length;
|
const last = !message?.children?.length;
|
||||||
const edit = message.messageId == currentEditId;
|
const edit = message.messageId == currentEditId;
|
||||||
const { ask } = useMessageHandler();
|
const { ask } = useMessageHandler();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
// const currentConvo = convoMap[message.conversationId];
|
||||||
|
|
||||||
// const notUser = !isCreatedByUser; // sender.toLowerCase() !== 'user';
|
// const notUser = !isCreatedByUser; // sender.toLowerCase() !== 'user';
|
||||||
// const blinker = submitting && isSubmitting && last && !isCreatedByUser;
|
// const blinker = submitting && isSubmitting && last && !isCreatedByUser;
|
||||||
|
|
@ -62,7 +61,7 @@ export default function Message({
|
||||||
}
|
}
|
||||||
}, [last, message]);
|
}, [last, message]);
|
||||||
|
|
||||||
const enterEdit = (cancel) => setCurrentEditId(cancel ? -1 : message.messageId);
|
const enterEdit = cancel => setCurrentEditId(cancel ? -1 : message.messageId);
|
||||||
|
|
||||||
const handleWheel = () => {
|
const handleWheel = () => {
|
||||||
if (blinker) {
|
if (blinker) {
|
||||||
|
|
@ -92,11 +91,10 @@ export default function Message({
|
||||||
'w-full border-b border-black/10 bg-gray-50 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-100 dark:bg-[#444654]';
|
'w-full border-b border-black/10 bg-gray-50 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-100 dark:bg-[#444654]';
|
||||||
|
|
||||||
if (message.bg && searchResult) {
|
if (message.bg && searchResult) {
|
||||||
props.className = message.bg + ' cursor-pointer';
|
props.className = message.bg.split('hover')[0];
|
||||||
|
props.titleClass = message.bg.split(props.className)[1] + ' cursor-pointer';
|
||||||
}
|
}
|
||||||
|
|
||||||
// const wrapText = (text) => <TextWrapper text={text} generateCursor={generateCursor}/>;
|
|
||||||
|
|
||||||
const resubmitMessage = () => {
|
const resubmitMessage = () => {
|
||||||
const text = textEditor.current.innerText;
|
const text = textEditor.current.innerText;
|
||||||
|
|
||||||
|
|
@ -135,11 +133,11 @@ export default function Message({
|
||||||
<div
|
<div
|
||||||
{...props}
|
{...props}
|
||||||
onWheel={handleWheel}
|
onWheel={handleWheel}
|
||||||
onClick={clickSearchResult}
|
// onClick={clickSearchResult}
|
||||||
>
|
>
|
||||||
<div className="relative m-auto flex gap-4 p-4 text-base md:max-w-2xl md:gap-6 md:py-6 lg:max-w-2xl lg:px-0 xl:max-w-3xl">
|
<div className="relative m-auto flex gap-4 p-4 text-base md:max-w-2xl md:gap-6 md:py-6 lg:max-w-2xl lg:px-0 xl:max-w-3xl">
|
||||||
<div className="relative flex h-[30px] w-[30px] flex-col items-end text-right text-xs md:text-sm">
|
<div className="relative flex h-[30px] w-[30px] flex-col items-end text-right text-xs md:text-sm">
|
||||||
{typeof icon === 'string' && icon.match(/[^\u0000-\u007F]+/) ? (
|
{typeof icon === 'string' && icon.match(/[^\\x00-\\x7F]+/) ? (
|
||||||
<span className=" direction-rtl w-40 overflow-x-scroll">{icon}</span>
|
<span className=" direction-rtl w-40 overflow-x-scroll">{icon}</span>
|
||||||
) : (
|
) : (
|
||||||
icon
|
icon
|
||||||
|
|
@ -153,6 +151,13 @@ export default function Message({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex w-[calc(100%-50px)] flex-col gap-1 whitespace-pre-wrap md:gap-3 lg:w-[calc(100%-115px)]">
|
<div className="relative flex w-[calc(100%-50px)] flex-col gap-1 whitespace-pre-wrap md:gap-3 lg:w-[calc(100%-115px)]">
|
||||||
|
{searchResult && (
|
||||||
|
<SubRow
|
||||||
|
classes={props.titleClass + ' rounded'}
|
||||||
|
subclasses="switch-result pl-2 pb-2"
|
||||||
|
onClick={clickSearchResult}
|
||||||
|
>{`${message.title} | ${message.sender}`}</SubRow>
|
||||||
|
)}
|
||||||
<div className="flex flex-grow flex-col gap-3">
|
<div className="flex flex-grow flex-col gap-3">
|
||||||
{error ? (
|
{error ? (
|
||||||
<div className="flex flex min-h-[20px] flex-grow flex-col items-start gap-4 gap-2 whitespace-pre-wrap text-red-500">
|
<div className="flex flex min-h-[20px] flex-grow flex-col items-start gap-4 gap-2 whitespace-pre-wrap text-red-500">
|
||||||
|
|
@ -207,15 +212,13 @@ export default function Message({
|
||||||
visible={!error && isCreatedByUser && !edit && !searchResult}
|
visible={!error && isCreatedByUser && !edit && !searchResult}
|
||||||
onClick={() => enterEdit()}
|
onClick={() => enterEdit()}
|
||||||
/>
|
/>
|
||||||
<div className="sibling-switch-container flex justify-between">
|
<SubRow subclasses="switch-container">
|
||||||
<div className="flex items-center justify-center gap-1 self-center pt-2 text-xs">
|
<SiblingSwitch
|
||||||
<SiblingSwitch
|
siblingIdx={siblingIdx}
|
||||||
siblingIdx={siblingIdx}
|
siblingCount={siblingCount}
|
||||||
siblingCount={siblingCount}
|
setSiblingIdx={setSiblingIdx}
|
||||||
setSiblingIdx={setSiblingIdx}
|
/>
|
||||||
/>
|
</SubRow>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
38
client/src/components/Messages/MessageBar.jsx
Normal file
38
client/src/components/Messages/MessageBar.jsx
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import React, { useRef, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
const MessageBar = ({ children, dynamicProps, handleWheel, clickSearchResult }) => {
|
||||||
|
const ref = useRef(null);
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
([entry]) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setIsVisible(true);
|
||||||
|
observer.unobserve(ref.current);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.1 }
|
||||||
|
);
|
||||||
|
|
||||||
|
observer.observe(ref.current);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.unobserve(ref.current);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...dynamicProps}
|
||||||
|
onWheel={handleWheel}
|
||||||
|
// onClick={clickSearchResult}
|
||||||
|
|
||||||
|
ref={ref}
|
||||||
|
>
|
||||||
|
{isVisible ? children : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MessageBar;
|
||||||
|
|
@ -75,7 +75,7 @@ export default function Messages({ messages, messageTree }) {
|
||||||
<div className="flex w-full items-center justify-center gap-1 border-b border-black/10 bg-gray-50 p-3 text-sm text-gray-500 dark:border-gray-900/50 dark:bg-gray-700 dark:text-gray-300">
|
<div className="flex w-full items-center justify-center gap-1 border-b border-black/10 bg-gray-50 p-3 text-sm text-gray-500 dark:border-gray-900/50 dark:bg-gray-700 dark:text-gray-300">
|
||||||
Model: {modelName} {customModel ? `(${customModel})` : null}
|
Model: {modelName} {customModel ? `(${customModel})` : null}
|
||||||
</div>
|
</div>
|
||||||
{(messageTree.length === 0) ? (
|
{(messageTree.length === 0 || messages.length === 0 || !messages) ? (
|
||||||
<Spinner />
|
<Spinner />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { setNewConvo } from '~/store/convoSlice';
|
import { setNewConvo, refreshConversation } from '~/store/convoSlice';
|
||||||
import { setMessages } from '~/store/messageSlice';
|
import { setMessages } from '~/store/messageSlice';
|
||||||
import { setSubmission } from '~/store/submitSlice';
|
import { setSubmission, setDisabled } from '~/store/submitSlice';
|
||||||
import { setText } from '~/store/textSlice';
|
import { setText } from '~/store/textSlice';
|
||||||
|
import { setInputValue, setQuery } from '~/store/searchSlice';
|
||||||
|
|
||||||
export default function NewChat() {
|
export default function NewChat() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
@ -12,7 +13,11 @@ export default function NewChat() {
|
||||||
dispatch(setText(''));
|
dispatch(setText(''));
|
||||||
dispatch(setMessages([]));
|
dispatch(setMessages([]));
|
||||||
dispatch(setNewConvo());
|
dispatch(setNewConvo());
|
||||||
|
dispatch(refreshConversation());
|
||||||
dispatch(setSubmission({}));
|
dispatch(setSubmission({}));
|
||||||
|
dispatch(setDisabled(false));
|
||||||
|
dispatch(setInputValue(''));
|
||||||
|
dispatch(setQuery(''));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import React, { useState, useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { Search } from 'lucide-react';
|
import { Search } from 'lucide-react';
|
||||||
import { setQuery } from '~/store/searchSlice';
|
import { setInputValue, setQuery } from '~/store/searchSlice';
|
||||||
|
|
||||||
export default function SearchBar({ fetch, clearSearch }) {
|
export default function SearchBar({ fetch, clearSearch }) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [inputValue, setInputValue] = useState('');
|
const { inputValue } = useSelector((state) => state.search);
|
||||||
|
// const [inputValue, setInputValue] = useState('');
|
||||||
|
|
||||||
const debouncedChangeHandler = useCallback(
|
const debouncedChangeHandler = useCallback(
|
||||||
debounce((q) => {
|
debounce((q) => {
|
||||||
|
|
@ -28,10 +29,9 @@ export default function SearchBar({ fetch, clearSearch }) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const changeHandler = (e) => {
|
const changeHandler = (e) => {
|
||||||
let q = e.target.value;
|
let q = e.target.value;
|
||||||
setInputValue(q);
|
dispatch(setInputValue(q));
|
||||||
q = q.trim();
|
q = q.trim();
|
||||||
|
|
||||||
if (q === '') {
|
if (q === '') {
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,10 @@ export default function Nav({ navVisible, setNavVisible }) {
|
||||||
const clearSearch = () => {
|
const clearSearch = () => {
|
||||||
setPage(1);
|
setPage(1);
|
||||||
dispatch(refreshConversation());
|
dispatch(refreshConversation());
|
||||||
dispatch(setNewConvo());
|
if (!conversationId) {
|
||||||
dispatch(setMessages([]));
|
dispatch(setNewConvo());
|
||||||
|
dispatch(setMessages([]));
|
||||||
|
}
|
||||||
dispatch(setDisabled(false));
|
dispatch(setDisabled(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
.sibling-switch-container {
|
.switch-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.switch-result {
|
||||||
|
display: block !important;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1024px) {
|
@media (max-width: 1024px) {
|
||||||
/* .sibling-switch {
|
/* .sibling-switch {
|
||||||
left: 114px;
|
left: 114px;
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,15 @@ const initialState = {
|
||||||
refreshConvoHint: 0,
|
refreshConvoHint: 0,
|
||||||
search: false,
|
search: false,
|
||||||
latestMessage: null,
|
latestMessage: null,
|
||||||
convos: []
|
convos: [],
|
||||||
|
convoMap: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentSlice = createSlice({
|
const currentSlice = createSlice({
|
||||||
name: 'convo',
|
name: 'convo',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
refreshConversation: (state, action) => {
|
refreshConversation: (state) => {
|
||||||
state.refreshConvoHint = state.refreshConvoHint + 1;
|
state.refreshConvoHint = state.refreshConvoHint + 1;
|
||||||
},
|
},
|
||||||
setConversation: (state, action) => {
|
setConversation: (state, action) => {
|
||||||
|
|
@ -69,6 +70,13 @@ const currentSlice = createSlice({
|
||||||
} else {
|
} else {
|
||||||
state.convos = convos.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
state.convos = convos.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// state.convoMap = convos.reduce((acc, curr) => {
|
||||||
|
// acc[curr.conversationId] = { ...curr };
|
||||||
|
// delete acc[curr.conversationId].conversationId;
|
||||||
|
// return acc;
|
||||||
|
// }, {});
|
||||||
|
|
||||||
},
|
},
|
||||||
setPages: (state, action) => {
|
setPages: (state, action) => {
|
||||||
state.pages = action.payload;
|
state.pages = action.payload;
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,16 @@ const initialState = {
|
||||||
searchEnabled: false,
|
searchEnabled: false,
|
||||||
search: false,
|
search: false,
|
||||||
query: '',
|
query: '',
|
||||||
|
inputValue: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const currentSlice = createSlice({
|
const currentSlice = createSlice({
|
||||||
name: 'search',
|
name: 'search',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
setInputValue: (state, action) => {
|
||||||
|
state.inputValue = action.payload;
|
||||||
|
},
|
||||||
setSearchState: (state, action) => {
|
setSearchState: (state, action) => {
|
||||||
state.searchEnabled = action.payload;
|
state.searchEnabled = action.payload;
|
||||||
},
|
},
|
||||||
|
|
@ -26,6 +30,6 @@ const currentSlice = createSlice({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setSearchState, setQuery } = currentSlice.actions;
|
export const { setInputValue, setSearchState, setQuery } = currentSlice.actions;
|
||||||
|
|
||||||
export default currentSlice.reducer;
|
export default currentSlice.reducer;
|
||||||
|
|
|
||||||
|
|
@ -21,31 +21,32 @@ export default function buildTree(messages, groupAll = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group all messages into one tree
|
// Group all messages into one tree
|
||||||
// let parentId = null;
|
let parentId = null;
|
||||||
// messages.forEach((message, i) => {
|
messages.forEach((message, i) => {
|
||||||
// messageMap[message.messageId] = { ...message, bg: i % 2 === 0 ? even : odd, children: [] };
|
messageMap[message.messageId] = { ...message, bg: i % 2 === 0 ? even : odd, children: [] };
|
||||||
// const currentMessage = messageMap[message.messageId];
|
const currentMessage = messageMap[message.messageId];
|
||||||
// const parentMessage = messageMap[parentId];
|
const parentMessage = messageMap[parentId];
|
||||||
// if (parentMessage) parentMessage.children.push(currentMessage);
|
if (parentMessage) parentMessage.children.push(currentMessage);
|
||||||
// else rootMessages.push(currentMessage);
|
else rootMessages.push(currentMessage);
|
||||||
// parentId = message.messageId;
|
parentId = message.messageId;
|
||||||
// });
|
|
||||||
|
|
||||||
// return rootMessages;
|
|
||||||
|
|
||||||
// Group all messages by conversation
|
|
||||||
// Traverse the messages array and store each element in messageMap.
|
|
||||||
rootMessages = {};
|
|
||||||
let parents = 0;
|
|
||||||
messages.forEach(message => {
|
|
||||||
if (message.conversationId in messageMap) {
|
|
||||||
messageMap[message.conversationId].children.push(message);
|
|
||||||
} else {
|
|
||||||
messageMap[message.conversationId] = { ...message, bg: parents % 2 === 0 ? even : odd, children: [] };
|
|
||||||
rootMessages[message.conversationId] = messageMap[message.conversationId];
|
|
||||||
parents++;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return Object.values(rootMessages);
|
return rootMessages;
|
||||||
|
|
||||||
|
// Group all messages by conversation, doesn't look great
|
||||||
|
// Traverse the messages array and store each element in messageMap.
|
||||||
|
// rootMessages = {};
|
||||||
|
// let parents = 0;
|
||||||
|
// messages.forEach(message => {
|
||||||
|
// if (message.conversationId in messageMap) {
|
||||||
|
// messageMap[message.conversationId].children.push(message);
|
||||||
|
// } else {
|
||||||
|
// messageMap[message.conversationId] = { ...message, bg: parents % 2 === 0 ? even : odd, children: [] };
|
||||||
|
// rootMessages.push(messageMap[message.conversationId]);
|
||||||
|
// parents++;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // return Object.values(rootMessages);
|
||||||
|
// return rootMessages;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue