Skip to content

Commit 12b184a

Browse files
committed
Add conversation management
1 parent 1e5ff8f commit 12b184a

File tree

1 file changed

+198
-11
lines changed

1 file changed

+198
-11
lines changed

index.html

+198-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<html>
33
<head>
44
<meta charset="utf-8" />
5+
<meta name="description" content="ChatGPT API Demo" />
56
<meta name="viewport" content="width=device-width, height=device-height" />
67
<title>OpenAI Chat</title>
78
<style>
@@ -25,9 +26,15 @@
2526
button {
2627
border: none;
2728
background-color: transparent;
28-
color: white;
29+
color: inherit;
30+
padding: 0;
2931
cursor: pointer;
3032
}
33+
ul {
34+
list-style: none;
35+
padding: 0;
36+
margin: 0;
37+
}
3138
#app {
3239
display: flex;
3340
flex-direction: column;
@@ -43,14 +50,47 @@
4350
background-color: #333;
4451
color: white;
4552
}
46-
header>button {
53+
header > button {
4754
position: absolute;
4855
padding: 12px;
4956
}
57+
button.menu {
58+
left: 0;
59+
}
5060
button.clear {
5161
right: 0;
62+
}
63+
.hidden {
64+
display: none;
65+
}
66+
aside {
67+
position: fixed;
68+
top: 0;
69+
width: 100%;
5270
height: 100%;
53-
font-size: 16px;
71+
z-index: 1;
72+
display: flex;
73+
}
74+
.sidebar-container {
75+
background-color: #333;
76+
color: white;
77+
width: 300px;
78+
overflow-y: auto;
79+
}
80+
.sidebar-modal {
81+
flex: 1 0;
82+
min-width: 64px;
83+
background-color: rgba(0, 0, 0, 0.3);
84+
}
85+
li > button {
86+
width: 100%;
87+
height: 48px;
88+
text-align: left;
89+
padding: 0 16px;
90+
transition: background-color 0.2s;
91+
}
92+
li > button:hover {
93+
background-color: rgba(255, 255, 255, 0.1);
5494
}
5595
main {
5696
flex-grow: 1;
@@ -215,30 +255,135 @@
215255
);
216256
}
217257

258+
export function Sidebar({
259+
numConversations,
260+
onConversationClick,
261+
onModalClick,
262+
onClearClick,
263+
onSettingsClick,
264+
}) {
265+
return [
266+
React.createElement(
267+
"div",
268+
{ key: "sidebar-container", className: "sidebar-container" },
269+
[
270+
React.createElement("ul", { key: "list" }, [
271+
React.createElement("li", { key: "new" }, [
272+
React.createElement(
273+
"button",
274+
{
275+
key: "new",
276+
onClick: () => {
277+
onConversationClick && onConversationClick(-1);
278+
},
279+
},
280+
"New Chat"
281+
),
282+
]),
283+
...Array(numConversations)
284+
.fill(null)
285+
.map((_, index) => {
286+
return React.createElement("li", { key: index }, [
287+
React.createElement(
288+
"button",
289+
{
290+
key: `conversation-${index}`,
291+
onClick: () => {
292+
onConversationClick && onConversationClick(index);
293+
},
294+
},
295+
`Conversation ${index + 1}`
296+
),
297+
]);
298+
}),
299+
React.createElement("li", { key: "clear" }, [
300+
React.createElement(
301+
"button",
302+
{
303+
key: "clear",
304+
onClick: () => {
305+
onClearClick && onClearClick();
306+
},
307+
},
308+
"Clear Conversations"
309+
),
310+
]),
311+
React.createElement("li", { key: "settings" }, [
312+
React.createElement(
313+
"button",
314+
{
315+
key: "settings",
316+
onClick: () => {
317+
onSettingsClick && onSettingsClick();
318+
},
319+
},
320+
"Settings"
321+
),
322+
]),
323+
]),
324+
]
325+
),
326+
React.createElement("div", {
327+
key: "sidebar-modal",
328+
className: "sidebar-modal",
329+
onClick: () => {
330+
onModalClick && onModalClick();
331+
},
332+
}),
333+
];
334+
}
335+
218336
export function App() {
219337
let token = null;
220338
getApiUrl().then(() => {
221339
if (getApiUrl.tokenRequired) token = getToken();
222340
});
223-
const sessions = JSON.parse(localStorage.getItem("sessions") || "[]");
224-
sessions[0] = sessions[0] || [];
341+
const conversations = JSON.parse(
342+
localStorage.getItem("conversations") || "[]"
343+
);
344+
conversations[0] = conversations[0] || [];
225345

226-
const [messages, setMessages] = React.useState(sessions[0]);
346+
const [conversationIndex, setConversationIndex] = React.useState(0);
347+
const [numConversations, setNumConversations] = React.useState(
348+
conversations.length
349+
);
350+
const [messages, setMessages] = React.useState(
351+
conversations[conversationIndex]
352+
);
227353
const messagesRef = React.useRef(messages);
228-
const saveMessages = (value) => {
354+
const saveMessages = (value, index) => {
229355
setMessages(value);
230-
localStorage.setItem("sessions", JSON.stringify([value]));
356+
conversations[index] = value;
357+
localStorage.setItem("conversations", JSON.stringify(conversations));
231358
};
232359

360+
const [showSidebar, setShowSidebar] = React.useState(false);
361+
233362
return [
234363
React.createElement("header", { key: "header" }, [
235364
React.createElement("span", { key: "title" }, "OpenAI Chat"),
365+
React.createElement(
366+
"button",
367+
{
368+
key: "menu",
369+
onClick: () => {
370+
setShowSidebar(!showSidebar);
371+
},
372+
className: "menu",
373+
},
374+
React.createElement("img", {
375+
src: "/assets/img/menu.svg",
376+
width: "24",
377+
height: "24",
378+
alt: "Menu",
379+
})
380+
),
236381
React.createElement(
237382
"button",
238383
{
239384
key: "clear",
240385
onClick: () => {
241-
saveMessages([]);
386+
saveMessages([], conversationIndex);
242387
messagesRef.current = [];
243388
},
244389
className: "clear",
@@ -252,6 +397,45 @@
252397
),
253398
]),
254399

400+
React.createElement(
401+
"aside",
402+
{
403+
key: "sidebar",
404+
className: showSidebar ? "sidebar" : "sidebar hidden",
405+
},
406+
407+
React.createElement(Sidebar, {
408+
messages,
409+
key: "sidebar",
410+
numConversations,
411+
412+
onConversationClick: (index) => {
413+
if (index === -1) {
414+
conversations.unshift([]);
415+
setNumConversations(conversations.length);
416+
index = 0;
417+
}
418+
setConversationIndex(index);
419+
saveMessages(conversations[index], index);
420+
messagesRef.current = conversations[index];
421+
setShowSidebar(false);
422+
},
423+
424+
onModalClick: () => {
425+
setShowSidebar(false);
426+
},
427+
428+
onClearClick: () => {
429+
localStorage.removeItem("conversations");
430+
setNumConversations(1);
431+
setConversationIndex(0);
432+
messagesRef.current = [];
433+
setMessages([]);
434+
setShowSidebar(false);
435+
},
436+
})
437+
),
438+
255439
React.createElement(
256440
"main",
257441
{ key: "main" },
@@ -282,13 +466,16 @@
282466
...messagesRef.current,
283467
{ role: "user", content: message },
284468
];
285-
saveMessages(messagesRef.current);
469+
saveMessages(messagesRef.current, conversationIndex);
286470
try {
287471
const completion = await complete(
288472
messagesRef.current,
289473
token,
290474
(message) =>
291-
saveMessages([...messagesRef.current, message])
475+
saveMessages(
476+
[...messagesRef.current, message],
477+
conversationIndex
478+
)
292479
);
293480
messagesRef.current = [...messagesRef.current, completion];
294481
} catch (error) {

0 commit comments

Comments
 (0)