返回提交历史
Modified
g4f/gui/client/css/style.css
+21
-1
Modified
g4f/gui/client/js/chat.v1.js
+74
-22
XFEstudio/gpt4free
Add remove messages from history Improve hidding regenerated messages
43cb4e61
代码差异
2 个文件
+95
-23
@@ -316,13 +316,33 @@ body {
316
316
z-index: 1000;
317
317
}
318
318
319
.message .assistant i {
319
.message .assistant .fa-phone-arrow-up-right,
320
.message .assistant .fa-phone-arrow-down-left {
320
321
position: absolute;
321
322
bottom: -6px;
322
323
right: -6px;
323
324
z-index: 1000;
324
325
}
325
326
327
.message .assistant .fa-xmark,
328
.message .user .fa-xmark {
329
position: absolute;
330
top: -2px;
331
left: 0px;
332
z-index: 1000;
333
display: none;
334
cursor: pointer;
335
}
336
337
.message .user .fa-xmark {
338
color: var(--colour-1);
339
}
340
341
.message .assistant:hover .fa-xmark,
342
.message .user:hover .fa-xmark {
343
display: block;
344
}
345
326
346
.new_convo {
327
347
padding: 8px 12px;
328
348
display: flex;
@@ -46,6 +46,22 @@ const highlight = (container) => {
46
46
);
47
47
}
48
48
49
const register_remove_message = async () => {
50
document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
51
if (!("click" in el.dataset)) {
52
el.dataset.click = "true";
53
el.addEventListener("click", async () => {
54
if (prompt_lock) {
55
return;
56
}
57
const message_el = el.parentElement.parentElement;
58
await remove_message(window.conversation_id, message_el.dataset.index);
59
await load_conversation(window.conversation_id);
60
})
61
}
62
});
63
}
64
49
65
const delete_conversations = async () => {
50
66
localStorage.clear();
51
67
await new_conversation();
@@ -58,13 +74,14 @@ const handle_ask = async () => {
58
74
message = message_input.value
59
75
if (message.length > 0) {
60
76
message_input.value = '';
77
prompt_lock = true;
61
78
await add_conversation(window.conversation_id, message);
62
79
if ("text" in fileInput.dataset) {
63
80
message += '\n```' + fileInput.dataset.type + '\n';
64
81
message += fileInput.dataset.text;
65
82
message += '\n```'
66
83
}
67
await add_message(window.conversation_id, "user", message);
84
let message_index = await add_message(window.conversation_id, "user", message);
68
85
window.token = message_id();
69
86
70
87
if (imageInput.dataset.src) URL.revokeObjectURL(imageInput.dataset.src);
@@ -73,9 +90,10 @@ const handle_ask = async () => {
73
90
else delete imageInput.dataset.src
74
91
75
92
message_box.innerHTML += `
76
<div class="message">
93
<div class="message" data-index="${message_index}">
77
94
<div class="user">
78
95
${user_image}
96
<i class="fa-solid fa-xmark"></i>
79
97
<i class="fa-regular fa-phone-arrow-up-right"></i>
80
98
</div>
81
99
<div class="content" id="user_${token}">
@@ -87,6 +105,7 @@ const handle_ask = async () => {
87
105
</div>
88
106
</div>
89
107
`;
108
await register_remove_message();
90
109
highlight(message_box);
91
110
await ask_gpt();
92
111
}
@@ -105,18 +124,24 @@ const ask_gpt = async () => {
105
124
regenerate.classList.add(`regenerate-hidden`);
106
125
messages = await get_messages(window.conversation_id);
107
126
108
// Remove generated images from history
127
// Remove history, if it is selected
128
if (document.getElementById('history')?.checked) {
129
messages = [messages[messages.length-1]]
130
}
131
132
new_messages = [];
109
133
for (i in messages) {
110
messages[i]["content"] = messages[i]["content"].replaceAll(
134
new_message = messages[i];
135
// Remove generated images from history
136
new_message["content"] = new_message["content"].replaceAll(
111
137
/<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
112
138
""
113
139
)
114
delete messages[i]["provider"];
115
}
116
117
// Remove history, if it is selected
118
if (document.getElementById('history')?.checked) {
119
messages = [messages[messages.length-1]]
140
delete new_message["provider"];
141
// Remove regenerated messages
142
if (!new_message.regenerate) {
143
new_messages.push(new_message)
144
}
120
145
}
121
146
122
147
window.scrollTo(0, 0);
@@ -125,7 +150,6 @@ const ask_gpt = async () => {
125
150
jailbreak = document.getElementById("jailbreak");
126
151
provider = document.getElementById("provider");
127
152
model = document.getElementById("model");
128
prompt_lock = true;
129
153
window.text = '';
130
154
131
155
stop_generating.classList.remove(`stop_generating-hidden`);
@@ -136,9 +160,11 @@ const ask_gpt = async () => {
136
160
window.scrollTo(0, 0);
137
161
138
162
message_box.innerHTML += `
139
<div class="message">
163
<div class="message" data-index="${new_messages.length}">
140
164
<div class="assistant">
141
${gpt_image} <i class="fa-regular fa-phone-arrow-down-left"></i>
165
${gpt_image}
166
<i class="fa-solid fa-xmark"></i>
167
<i class="fa-regular fa-phone-arrow-down-left"></i>
142
168
</div>
143
169
<div class="content" id="gpt_${window.token}">
144
170
<div class="provider"></div>
@@ -160,7 +186,7 @@ const ask_gpt = async () => {
160
186
web_search: document.getElementById(`switch`).checked,
161
187
provider: provider.options[provider.selectedIndex].value,
162
188
patch_provider: document.getElementById('patch').checked,
163
messages: messages
189
messages: new_messages
164
190
});
165
191
const headers = {
166
192
accept: 'text/event-stream'
@@ -185,7 +211,6 @@ const ask_gpt = async () => {
185
211
window.scrollTo(0, 0);
186
212
187
213
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
188
189
214
error = provider = null;
190
215
while (true) {
191
216
const { value, done } = await reader.read();
@@ -252,9 +277,12 @@ const ask_gpt = async () => {
252
277
}
253
278
let cursorDiv = document.getElementById(`cursor`);
254
279
if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
255
add_message(window.conversation_id, "assistant", text, provider);
280
if (text) {
281
add_message(window.conversation_id, "assistant", text, provider);
282
}
256
283
message_box.scrollTop = message_box.scrollHeight;
257
284
await remove_cancel_button();
285
await register_remove_message();
258
286
prompt_lock = false;
259
287
window.scrollTo(0, 0);
260
288
await load_conversations(20, 0);
@@ -342,7 +370,8 @@ const load_conversation = async (conversation_id) => {
342
370
let messages = await get_messages(conversation_id);
343
371
344
372
let elements = "";
345
for (item of messages) {
373
for (i in messages) {
374
let item = messages[i];
346
375
let provider = item.provider ? `
347
376
<div class="provider">
348
377
<a href="${item.provider.url}" target="_blank">${item.provider.name}</a>
@@ -350,9 +379,10 @@ const load_conversation = async (conversation_id) => {
350
379
</div>
351
380
` : "";
352
381
elements += `
353
<div class="message">
382
<div class="message" data-index="${i}">
354
383
<div class=${item.role == "assistant" ? "assistant" : "user"}>
355
384
${item.role == "assistant" ? gpt_image : user_image}
385
<i class="fa-solid fa-xmark"></i>
356
386
${item.role == "assistant"
357
387
? `<i class="fa-regular fa-phone-arrow-down-left"></i>`
358
388
: `<i class="fa-regular fa-phone-arrow-up-right"></i>`
@@ -367,6 +397,7 @@ const load_conversation = async (conversation_id) => {
367
397
}
368
398
message_box.innerHTML = elements;
369
399
400
await register_remove_message();
370
401
highlight(message_box);
371
402
372
403
message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
@@ -409,11 +440,30 @@ const add_conversation = async (conversation_id, content) => {
409
440
history.pushState({}, null, `/chat/${conversation_id}`);
410
441
};
411
442
412
const remove_last_message = async (conversation_id) => {
443
const hide_last_message = async (conversation_id) => {
413
444
const conversation = await get_conversation(conversation_id)
445
const last_message = conversation.items.pop();
446
last_message["regenerate"] = true;
447
conversation.items.push(last_message);
414
448
415
conversation.items.pop();
449
localStorage.setItem(
450
`conversation:${conversation_id}`,
451
JSON.stringify(conversation)
452
);
453
};
416
454
455
const remove_message = async (conversation_id, index) => {
456
const conversation = await get_conversation(conversation_id);
457
let new_items = [];
458
for (i in conversation.items) {
459
if (i == index - 1) {
460
delete conversation.items[i]["regenerate"];
461
}
462
if (i != index) {
463
new_items.push(conversation.items[i])
464
}
465
}
466
conversation.items = new_items;
417
467
localStorage.setItem(
418
468
`conversation:${conversation_id}`,
419
469
JSON.stringify(conversation)
@@ -433,6 +483,8 @@ const add_message = async (conversation_id, role, content, provider) => {
433
483
`conversation:${conversation_id}`,
434
484
JSON.stringify(conversation)
435
485
);
486
487
return conversation.items.length - 1;
436
488
};
437
489
438
490
const load_conversations = async (limit, offset, loader) => {
@@ -468,7 +520,8 @@ document.getElementById(`cancelButton`).addEventListener(`click`, async () => {
468
520
});
469
521
470
522
document.getElementById(`regenerateButton`).addEventListener(`click`, async () => {
471
await remove_last_message(window.conversation_id);
523
prompt_lock = true;
524
await hide_last_message(window.conversation_id);
472
525
window.token = message_id();
473
526
await ask_gpt();
474
527
});
@@ -591,7 +644,6 @@ colorThemes.forEach((themeOption) => {
591
644
});
592
645
});
593
646
594
595
647
window.onload = async () => {
596
648
setTheme();
597
649