-
Notifications
You must be signed in to change notification settings - Fork 0
/
chat.js
249 lines (206 loc) · 8.67 KB
/
chat.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Select the necessary elements from the DOM
const chatBox = document.querySelector('#chatBox');
const chatForm = document.querySelector('#chatForm');
const userInput = document.querySelector('#userInput');
const exportBtn = document.querySelector('#exportBtn');
const importBtn = document.querySelector('#importBtn');
const spinner = document.querySelector('#spinner');
const toggleDarkModeBtn = document.querySelector('#toggleDarkModeBtn');
const exportMdBtn = document.querySelector('#exportMdBtn');
const exportPinnedBtn = document.querySelector('#exportPinnedBtn');
// Initialize variables
let conversation = [];
let isConversationSaved = true;
let isFirstMessage = true;
let pinnedMessages = [];
// Add event listener for form submission
// Add event listener for form submission
chatForm.addEventListener('submit', async (e) => {
e.preventDefault();
const message = userInput.value;
if (isFirstMessage) {
const gameTypeSelect = document.querySelector('#gameType');
const gameType = gameTypeSelect.value;
const systemRoleSelect = document.querySelector('#systemRole');
const systemRole = systemRoleSelect.value;
const systemMessage = `${systemRole} Provide assistance on ${gameType}.`;
if (systemMessage) {
conversation.push({ role: 'system', content: systemMessage });
}
gameTypeSelect.disabled = true;
systemRoleSelect.disabled = true;
isFirstMessage = false;
}
addMessageToChatBox('user', message);
conversation.push({ role: 'user', content: message });
userInput.value = '';
spinner.style.display = 'block';
try {
const res = await fetch('http://localhost:8089/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: conversation })
});
if (res.ok) {
const data = await res.json();
const aiMessage = data.response.content;;
addMessageToChatBox('assistant', aiMessage);
conversation.push({ role: 'assistant', content: aiMessage });
} else {
throw new Error('Response not ok');
}
} catch (error) {
console.error(error);
addMessageToChatBox('assistant', 'Sorry, there was an error. Please try again.');
conversation.push({ role: 'assistant', content: 'Sorry, there was an error. Please try again.' });
} finally {
spinner.style.display = 'none';
}
isConversationSaved = false;
});
// Add event listener for export button click
exportBtn.addEventListener('click', () => {
// Create a download link for the conversation JSON file and click it
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([JSON.stringify(conversation)], { type: 'application/json' }));
a.download = 'conversation.json';
a.click();
isConversationSaved = true;
});
// Add event listener for import button change
importBtn.addEventListener('change', async (e) => {
// Read the selected file and replace the conversation with its contents
const file = e.target.files[0];
const text = await file.text();
conversation = JSON.parse(text);
chatBox.innerHTML = '';
conversation.forEach(msg => addMessageToChatBox(msg.role, msg.content));
isFirstMessage = false;
});
// Add function to add a message to the chat box
function addMessageToChatBox(role, message) {
const messageElem = document.createElement('p');
const roleElem = document.createElement('span');
roleElem.textContent = `${role === 'user' ? 'You' : 'Bob'}: `;
roleElem.style.color = role === 'user' ? 'yellow' : 'green';
roleElem.style.fontWeight = 'bold';
messageElem.appendChild(roleElem);
messageElem.innerHTML += message.replace(/\n/g, '<br>');
messageElem.style.whiteSpace = 'pre-wrap';
chatBox.appendChild(messageElem);
chatBox.scrollTop = chatBox.scrollHeight;
// Store the original message content along with its paragraph element
messageElem.messageContent = message;
// Add pin button to assistant messages
if (role === 'assistant') {
const pinBtn = document.createElement('button');
pinBtn.textContent = '📌'; // pin emoji
pinBtn.style.border = 'none';
pinBtn.style.background = 'none';
pinBtn.style.cursor = 'pointer';
pinBtn.addEventListener('click', () => pinMessage(messageElem));
messageElem.appendChild(pinBtn);
}
}
// Add a function to add a message to the pinned messages
function addMessageToPinnedMessages(message) {
if (pinnedMessages.indexOf(message) > -1) {
alert('This message is already pinned.');
return;
}
pinnedMessages.push(message);
const pinnedMessageElem = document.createElement('p');
pinnedMessageElem.textContent = '📍' + message;
pinnedMessageElem.style.cursor = 'pointer';
pinnedMessageElem.className = 'pinned-message'; // Assign the pinned-message class
// Add right-click event listener
pinnedMessageElem.addEventListener('contextmenu', function (event) {
event.preventDefault(); // Prevent the default right-click menu from showing
// Confirm with the user that they want to remove the pin
let confirmRemove = confirm('Are you sure you want to remove this pin?');
if (confirmRemove) {
// Remove the message from the array
const index = pinnedMessages.indexOf(message);
if (index > -1) {
pinnedMessages.splice(index, 1);
}
// Remove the message from the display
pinnedMessageElem.remove();
if (pinnedMessages.length === 0) {
exportPinnedBtn.style.display = 'none';
}
}
});
document.querySelector('#pinnedMessages').appendChild(pinnedMessageElem);
exportPinnedBtn.style.display = 'block';
}
// Add function to handle pinning of messages
function pinMessage(messageElem) {
const messageContent = messageElem.messageContent;
addMessageToPinnedMessages(messageContent);
}
// Add an event listener to the pinned messages div
document.querySelector('#pinnedMessages').addEventListener('click', function (event) {
if (event.target.tagName === 'P') {
showOverlay(event.target.textContent);
}
});
// Add a function to show the overlay
function showOverlay(content) {
document.querySelector('#overlayContent').textContent = content;
document.querySelector('#overlay').style.display = 'block';
}
// Add a function to hide the overlay
function hideOverlay() {
document.querySelector('#overlayContent').textContent = '';
document.querySelector('#overlay').style.display = 'none';
}
// Add an event listener to the overlay to hide it when clicked
document.querySelector('#overlay').addEventListener('click', hideOverlay);
// Add event listener for beforeunload to prompt the user to save the conversation
window.addEventListener('beforeunload', (event) => {
if (!isConversationSaved) {
event.preventDefault();
event.returnValue = '';
}
});
// Add event listener for toggle dark mode button click
toggleDarkModeBtn.addEventListener('click', () => {
document.body.classList.toggle('dark-mode');
document.body.classList.toggle('light-mode');
});
// Add event listener for export Markdown button click
exportMdBtn.addEventListener('click', () => {
// Convert the conversation to Markdown
const markdownConversation = conversation.map(messageToMarkdown).join('\n\n');
// Create a download link for the Markdown file and click it
const blob = new Blob([markdownConversation], { type: 'text/markdown' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'conversation.md';
a.click();
isConversationSaved = true;
});
// Helper function to convert a message object to a Markdown string
function messageToMarkdown(message) {
const speaker = message.role === 'user' ? 'You' : 'GPT-3';
return `**${speaker}**: ${message.content.replace(/\n/g, ' \n')}`;
}
function messageToMarkdown(message) {
return `* ${message}\n`;
}
exportPinnedBtn.addEventListener('click', () => {
// Convert the pinned messages to Markdown
const markdownPinnedMessages = pinnedMessages.map(messageToMarkdown).join('');
// Create a Blob with the Markdown content
const blob = new Blob([markdownPinnedMessages], { type: 'text/markdown' });
// Create a URL for the Blob
const url = URL.createObjectURL(blob);
// Create a download link and click it
const a = document.createElement('a');
a.href = url;
a.download = 'pinned_items.md';
a.click();
// Release the reference to the Blob
URL.revokeObjectURL(url);
});