Skip to content

Commit

Permalink
Merge pull request #7 from animalnots/dev
Browse files Browse the repository at this point in the history
Merge from dev
  • Loading branch information
animalnots authored Jul 7, 2024
2 parents 177a8a8 + 18678c4 commit 851ce66
Show file tree
Hide file tree
Showing 19 changed files with 418 additions and 85 deletions.
3 changes: 3 additions & 0 deletions public/locales/en/main.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"save": "Save",
"generate": "Generate",
"add_image_url": "Add image URL",
"enter_image_url_placeholder": "Enter image URL",
"cancel": "Cancel",
"confirm": "Confirm",
"warning": "Warning",
Expand Down Expand Up @@ -33,6 +35,7 @@
"total": "Total",
"resetCost": "Reset Costs",
"countTotalTokens": "Count total tokens",
"displayChatSize": "Display chat size in title",
"morePrompts": "You can find more prompts here: ",
"clearPrompts": "Clear prompts",
"postOnShareGPT": {
Expand Down
10 changes: 6 additions & 4 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ function App() {
return (
<div className='overflow-hidden w-full h-full relative'>
<Menu />
<Chat />
<ApiPopup />
<Toast />
<ToastContainer />
<div className={`flex h-full flex-1 flex-col`}>
<Chat />
<ApiPopup />
<Toast />
<ToastContainer />
</div>
</div>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import StopGeneratingButton from '@components/StopGeneratingButton/StopGeneratin

const Chat = () => {
const hideSideMenu = useStore((state) => state.hideSideMenu);
const menuWidth = useStore((state) => state.menuWidth);

return (
<div
className={`flex h-full flex-1 flex-col ${
hideSideMenu ? 'md:pl-0' : 'md:pl-[260px]'
}`}
className={`flex h-full flex-1 flex-col`}
style={{ paddingLeft: hideSideMenu ? '0' : `${menuWidth}px` }}
>
<MobileBar />
<main className='relative h-full w-full transition-width flex flex-col overflow-hidden items-stretch flex-1'>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Chat/ChatContent/ChatTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const ChatTitle = React.memo(() => {
return config ? (
<>
<div
className='flex gap-x-4 gap-y-1 flex-wrap w-full items-center justify-center border-b border-black/10 bg-gray-50 p-3 dark:border-gray-900/50 dark:bg-gray-700 text-gray-600 dark:text-gray-300 cursor-pointer'
className='sticky top-0 z-10 flex gap-x-4 gap-y-1 flex-wrap w-full items-center justify-center border-b border-black/10 bg-gray-50 p-3 dark:border-gray-900/50 dark:bg-gray-700 text-gray-600 dark:text-gray-300 cursor-pointer'
onClick={() => {
setIsModalOpen(true);
}}
Expand Down
23 changes: 17 additions & 6 deletions src/components/Chat/ChatContent/Message/View/ContentView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ import CrossIcon from '@icon/CrossIcon';

import useSubmit from '@hooks/useSubmit';

import { ChatInterface, ContentInterface, ImageContentInterface, TextContentInterface } from '@type/chat';
import {
ChatInterface,
ContentInterface,
ImageContentInterface,
TextContentInterface,
} from '@type/chat';

import { codeLanguageSubset } from '@constants/chat';

Expand All @@ -41,7 +46,7 @@ const ContentView = memo(
messageIndex,
}: {
role: string;
content: ContentInterface[],
content: ContentInterface[];
setIsEdit: React.Dispatch<React.SetStateAction<boolean>>;
messageIndex: number;
}) => {
Expand Down Expand Up @@ -132,13 +137,19 @@ const ContentView = memo(
{(content[0] as TextContentInterface).text}
</ReactMarkdown>
) : (
<span className='whitespace-pre-wrap'>{(content[0] as TextContentInterface).text}</span>
<span className='whitespace-pre-wrap'>
{(content[0] as TextContentInterface).text}
</span>
)}
</div>
<div className="flex gap-4">
<div className='flex gap-4'>
{(content.slice(1) as ImageContentInterface[]).map((image, index) => (
<div key={index} className="image-container">
<img src={image.image_url.url} alt={`uploaded-${index}`} className="h-20" />
<div key={index} className='image-container'>
<img
src={image.image_url.url}
alt={`uploaded-${index}`}
className='h-20'
/>
</div>
))}
</div>
Expand Down
131 changes: 87 additions & 44 deletions src/components/Chat/ChatContent/Message/View/EditView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const EditView = ({

const [_content, _setContent] = useState<ContentInterface[]>(content);
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const [imageUrl, setImageUrl] = useState<string>('');
const textareaRef = React.createRef<HTMLTextAreaElement>();

const { t } = useTranslation();
Expand Down Expand Up @@ -104,6 +105,22 @@ const EditView = ({
_setContent(updatedContent);
};

const handleImageUrlChange = () => {
if (imageUrl.trim() === '') return;

const newImage: ImageContentInterface = {
type: 'image_url',
image_url: {
detail: 'auto',
url: imageUrl,
},
};

const updatedContent = [..._content, newImage];
_setContent(updatedContent);
setImageUrl('');
};

const handleImageDetailChange = (index: number, detail: string) => {
const updatedImages = [..._content];
updatedImages[index + 1].image_url.detail = detail;
Expand Down Expand Up @@ -229,6 +246,9 @@ const EditView = ({
setIsEdit={setIsEdit}
_setContent={_setContent}
_content={_content}
imageUrl={imageUrl}
setImageUrl={setImageUrl}
handleImageUrlChange={handleImageUrlChange}
/>
{isModalOpen && (
<PopupModal
Expand All @@ -254,6 +274,9 @@ const EditViewButtons = memo(
setIsEdit,
_setContent,
_content,
imageUrl,
setImageUrl,
handleImageUrlChange,
}: {
sticky?: boolean;
handleFileChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
Expand All @@ -265,6 +288,9 @@ const EditViewButtons = memo(
setIsEdit: React.Dispatch<React.SetStateAction<boolean>>;
_setContent: React.Dispatch<React.SetStateAction<ContentInterface[]>>;
_content: ContentInterface[];
imageUrl: string;
setImageUrl: React.Dispatch<React.SetStateAction<string>>;
handleImageUrlChange: () => void;
}) => {
const { t } = useTranslation();
const generating = useStore.getState().generating;
Expand All @@ -286,65 +312,82 @@ const EditViewButtons = memo(
return (
<div>
{modelTypes[model] == 'image' && (
<div className='flex justify-center'>
<div className='flex gap-5'>
{_content.slice(1).map((image, index) => (
<div
key={index}
className='image-container flex flex-col gap-2'
>
<img
src={image.image_url.url}
alt={`uploaded-${index}`}
className='h-10'
/>
<div className='flex flex-row gap-3'>
<select
onChange={(event) =>
handleImageDetailChange(index, event.target.value)
}
title='Select image resolution'
aria-label='Select image resolution'
defaultValue={image.image_url.detail}
style={{ color: 'black' }}
>
<option value='auto'>Auto</option>
<option value='high'>High</option>
<option value='low'>Low</option>
</select>
<button
className='close-button'
onClick={() => handleRemoveImage(index)}
aria-label='Remove Image'
>
&times;
</button>
<>
<div className='flex justify-center'>
<div className='flex gap-5'>
{_content.slice(1).map((image, index) => (
<div
key={index}
className='image-container flex flex-col gap-2'
>
<img
src={image.image_url.url}
alt={`uploaded-${index}`}
className='h-10'
/>
<div className='flex flex-row gap-3'>
<select
onChange={(event) =>
handleImageDetailChange(index, event.target.value)
}
title='Select image resolution'
aria-label='Select image resolution'
defaultValue={image.image_url.detail}
style={{ color: 'black' }}
>
<option value='auto'>Auto</option>
<option value='high'>High</option>
<option value='low'>Low</option>
</select>
<button
className='close-button'
onClick={() => handleRemoveImage(index)}
aria-label='Remove Image'
>
&times;
</button>
</div>
</div>
</div>
))}
))}

<button
className='btn relative btn-neutral h-10'
onClick={handleUploadButtonClick}
aria-label={'Upload Images'}
>
<div className='flex items-center justify-center gap-2'>
<FolderIcon />
</div>
</button>
</div>
</div>
<div className='flex justify-center mt-4'>
<input
type='text'
value={imageUrl}
onChange={(e) => setImageUrl(e.target.value)}
placeholder={t('enter_image_url_placeholder') as string}
className='input input-bordered w-full max-w-xs text-gray-800 dark:text-white p-3 border-none bg-gray-200 dark:bg-gray-600 rounded-md m-0 w-full mr-0 h-10 focus:outline-none'
/>
<button
className='btn relative btn-neutral h-10'
onClick={handleUploadButtonClick}
aria-label={'Upload Images'}
className='btn btn-primary ml-2'
onClick={handleImageUrlChange}
aria-label={t('add_image_url') as string}
>
<div className='flex items-center justify-center gap-2'>
<FolderIcon />
</div>
{t('add_image_url')}
</button>
</div>

{/* Hidden file input */}
<input
type='file'
ref={fileInputRef}
style={{ display: 'none' }}
onChange={handleFileChange}
accept='image/*'
multiple
/>
</div>
</>
)}

<div className='flex'>
<div className='flex-1 text-center mt-2 flex justify-center'>
{sticky && (
Expand Down
20 changes: 18 additions & 2 deletions src/components/Menu/ChatFolder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,17 @@ import useHideOnOutsideClick from '@hooks/useHideOnOutsideClick';
const ChatFolder = ({
folderChats,
folderId,
selectedChats,
setSelectedChats,
lastSelectedIndex,
setLastSelectedIndex,
}: {
folderChats: ChatHistoryInterface[];
folderId: string;
selectedChats: number[];
setSelectedChats: (indices: number[]) => void;
lastSelectedIndex: number | null;
setLastSelectedIndex: (index: number) => void;
}) => {
const folderName = useStore((state) => state.folders[folderId]?.name);
const isExpanded = useStore((state) => state.folders[folderId]?.expanded);
Expand Down Expand Up @@ -116,12 +124,15 @@ const ChatFolder = ({
setFolders(updatedFolders);

// update chat folderId to new folderId
const chatIndex = Number(e.dataTransfer.getData('chatIndex'));
const chatIndices = JSON.parse(e.dataTransfer.getData('chatIndices'));
const updatedChats: ChatInterface[] = JSON.parse(
JSON.stringify(useStore.getState().chats)
);
updatedChats[chatIndex].folder = folderId;
chatIndices.forEach((chatIndex: number) => {
updatedChats[chatIndex].folder = folderId;
});
setChats(updatedChats);
setSelectedChats([]);
}
};

Expand Down Expand Up @@ -304,7 +315,12 @@ const ChatFolder = ({
<ChatHistory
title={chat.title}
chatIndex={chat.index}
chatSize={chat.chatSize}
key={`${chat.title}-${chat.index}`}
selectedChats={selectedChats}
setSelectedChats={setSelectedChats}
lastSelectedIndex={lastSelectedIndex}
setLastSelectedIndex={setLastSelectedIndex}
/>
))}
</div>
Expand Down
Loading

0 comments on commit 851ce66

Please sign in to comment.