diff --git a/README.md b/README.md
index 52e0423dc..e33eb46d4 100644
--- a/README.md
+++ b/README.md
@@ -12,23 +12,28 @@ Or click fork & run on Vercel
## Roadmap 🛣️
-🚨 **Apr'23 - Attention! We look for your input!** 🚨
+🚨 ** April 2023 - Attention! We look for your input!** 🚨
| Roadmap | RFC 📝 | Status | Description |
|:---------------------|-----------------------------------------------------------|:------:|:-----------------------------------------------------------------------------------------------------------------|
| Editable Purposes 🎭 | https://github.com/enricoros/nextjs-chatgpt-app/issues/35 | 💬 | In-app customization of 'Purposes', as many forks are created for that reason. |
| Templates sharing 🌐 | https://github.com/enricoros/nextjs-chatgpt-app/issues/35 | 💬 | Community repository of Purposes/Systems - Vote with 👍 and usage. Where to store? Bring your own key? Moderate? |
| Reasoning Systems 🧩 | https://github.com/enricoros/nextjs-chatgpt-app/issues/36 | 🤔 | ReAct, DEPS, Reflexion - shall we? |
-| Your epic idea | | 💡 | [Create RFC](https://github.com/enricoros/nextjs-chatgpt-app/issues/new?labels=RFC&body=Describe+the+idea) ❗ |
+| Your epic idea | | 💡 | [Create RFC](https://github.com/enricoros/nextjs-chatgpt-app/issues/new?labels=RFC&body=Describe+the+idea) ❗ |
## Features ✨
🚨 **We added cool new features to the app!** (bare-bones
was [466a36](https://github.com/enricoros/nextjs-chatgpt-app/tree/466a3667a48060d406d60943af01fe26366563fb))
+- [x] _NEW 04.10_ 🎉 **Multiple chats** 📝📝📝
+- [x] _NEW 04.09_ 🎉 **Microphone improvements** 🎙️
+- [x] _NEW 04.08_ 🎉 **Precise Token counter** 📊 extra-useful
+- [x] _NEW 04.08_ 🎉 Organization ID for OpenAI users
+- [x] _NEW 04.07_ 🎉 **Pixel-perfect Markdown** 🎨
- [x] _NEW 04.04_ 🎉 **Download JSON** to export/backup chats 📥
- [x] _NEW 04.03_ 🎉 **PDF import** 📄🔀🧠 (fredliubojin) <- "ask questions to a PDF!" 🤯
-- [x] _NEW 04.03_ 🎉 **Tokens utilization** 📊 [WIP]
+- [x] _NEW 04.03_ 🎉 **Tokens utilization** 📊 [Initial - just new messages, not full chat]

- [x] _NEW 04.02_ 🎉 **Markdown rendering** 🎨 (nilshulth) [WIP]
- [x] 🎉 **NEW 04.01** Typing Avatars
diff --git a/components/ApplicationBar.tsx b/components/ApplicationBar.tsx
index 3b0f2c665..bc743139f 100644
--- a/components/ApplicationBar.tsx
+++ b/components/ApplicationBar.tsx
@@ -3,8 +3,8 @@ import { shallow } from 'zustand/shallow';
import { IconButton, ListDivider, ListItemDecorator, Menu, MenuItem, Sheet, Stack, Switch, useColorScheme } from '@mui/joy';
import { SxProps } from '@mui/joy/styles/types';
+import ClearIcon from '@mui/icons-material/Clear';
import DarkModeIcon from '@mui/icons-material/DarkMode';
-import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
import ExitToAppIcon from '@mui/icons-material/ExitToApp';
import FileDownloadIcon from '@mui/icons-material/FileDownload';
import MenuIcon from '@mui/icons-material/Menu';
@@ -14,43 +14,40 @@ import SettingsSuggestIcon from '@mui/icons-material/SettingsSuggest';
import SwapVertIcon from '@mui/icons-material/SwapVert';
import { ChatModelId, ChatModels, SystemPurposeId, SystemPurposes } from '@/lib/data';
+import { ConfirmationModal } from '@/components/dialogs/ConfirmationModal';
import { PagesMenu } from '@/components/Pages';
import { StyledDropdown } from '@/components/util/StyledDropdown';
-import { useActiveConfiguration } from '@/lib/store-chats';
+import { useChatStore } from '@/lib/store-chats';
import { useSettingsStore } from '@/lib/store-settings';
/**
* The top bar of the application, with the model and purpose selection, and menu/settings icons
*/
-export function ApplicationBar({ onClearConversation, onDownloadConversationJSON, onPublishConversation, onShowSettings, sx }: {
- onClearConversation: (conversationId: (string | null)) => void;
- onDownloadConversationJSON: (conversationId: (string | null)) => void;
- onPublishConversation: (conversationId: (string | null)) => void;
+export function ApplicationBar(props: {
+ conversationId: string | null;
+ onDownloadConversationJSON: (conversationId: string) => void;
+ onPublishConversation: (conversationId: string) => void;
onShowSettings: () => void;
sx?: SxProps
}) {
// state
+ const [clearConfirmationId, setClearConfirmationId] = React.useState(null);
const [pagesMenuAnchor, setPagesMenuAnchor] = React.useState(null);
const [actionsMenuAnchor, setActionsMenuAnchor] = React.useState(null);
- // external state
+
+ // settings
+
const { mode: colorMode, setMode: setColorMode } = useColorScheme();
+
const { freeScroll, setFreeScroll, showSystemMessages, setShowSystemMessages } = useSettingsStore(state => ({
freeScroll: state.freeScroll, setFreeScroll: state.setFreeScroll,
showSystemMessages: state.showSystemMessages, setShowSystemMessages: state.setShowSystemMessages,
}), shallow);
- const { chatModelId, setChatModelId, setSystemPurposeId, systemPurposeId } = useActiveConfiguration();
-
-
- const handleChatModelChange = (event: any, value: ChatModelId | null) => value && setChatModelId(value);
-
- const handleSystemPurposeChange = (event: any, value: SystemPurposeId | null) => value && setSystemPurposeId(value);
-
const closePagesMenu = () => setPagesMenuAnchor(null);
-
const closeActionsMenu = () => setActionsMenuAnchor(null);
const handleDarkModeToggle = () => setColorMode(colorMode === 'dark' ? 'light' : 'dark');
@@ -61,25 +58,53 @@ export function ApplicationBar({ onClearConversation, onDownloadConversationJSON
const handleActionShowSettings = (e: React.MouseEvent) => {
e.stopPropagation();
- onShowSettings();
+ props.onShowSettings();
closeActionsMenu();
};
- const handleActionDownloadChatJson = (e: React.MouseEvent) => {
+
+ // conversation actions
+
+ const { isEmpty, chatModelId, systemPurposeId, setMessages, setChatModelId, setSystemPurposeId } = useChatStore(state => {
+ const conversation = state.conversations.find(conversation => conversation.id === props.conversationId);
+ return {
+ isEmpty: conversation ? !conversation.messages.length : true,
+ chatModelId: conversation ? conversation.chatModelId : null,
+ systemPurposeId: conversation ? conversation.systemPurposeId : null,
+ setMessages: state.setMessages,
+ setChatModelId: state.setChatModelId,
+ setSystemPurposeId: state.setSystemPurposeId,
+ };
+ }, shallow);
+
+ const handleConversationClear = (e: React.MouseEvent) => {
e.stopPropagation();
- onDownloadConversationJSON(null);
+ setClearConfirmationId(props.conversationId);
};
- const handleActionPublishChat = (e: React.MouseEvent) => {
- e.stopPropagation();
- onPublishConversation(null);
+ const handleConfirmedClearConversation = () => {
+ if (clearConfirmationId) {
+ setMessages(clearConfirmationId, []);
+ setClearConfirmationId(null);
+ }
};
- const handleActionClearConversation = (e: React.MouseEvent, id: string | null) => {
+ const handleConversationPublish = (e: React.MouseEvent) => {
e.stopPropagation();
- onClearConversation(id || null);
+ props.conversationId && props.onPublishConversation(props.conversationId);
};
+ const handleConversationDownload = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ props.conversationId && props.onDownloadConversationJSON(props.conversationId);
+ };
+
+ const handleChatModelChange = (event: any, value: ChatModelId | null) =>
+ value && props.conversationId && setChatModelId(props.conversationId, value);
+
+ const handleSystemPurposeChange = (event: any, value: SystemPurposeId | null) =>
+ value && props.conversationId && setSystemPurposeId(props.conversationId, value);
+
return <>
@@ -89,7 +114,7 @@ export function ApplicationBar({ onClearConversation, onDownloadConversationJSON
sx={{
p: 1,
display: 'flex', flexDirection: 'row', justifyContent: 'space-between',
- ...(sx || {}),
+ ...(props.sx || {}),
}}>
setPagesMenuAnchor(event.currentTarget)}>
@@ -98,9 +123,9 @@ export function ApplicationBar({ onClearConversation, onDownloadConversationJSON
-
+ {chatModelId && }
-
+ {systemPurposeId && }
@@ -111,11 +136,7 @@ export function ApplicationBar({ onClearConversation, onDownloadConversationJSON
{/* Left menu */}
- {}
+ {}
{/* Right menu */}
@@ -149,7 +170,7 @@ export function ApplicationBar({ onClearConversation, onDownloadConversationJSON
-