Update chat.js
Browse files- static/js/ui/chat.js +19 -8
static/js/ui/chat.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
|
|
| 1 |
// static/js/ui/chat.js
|
| 2 |
|
| 3 |
import * as state from '../state.js';
|
| 4 |
import * as db from '../db.js';
|
| 5 |
import { dom } from './dom.js';
|
| 6 |
-
import { toggleHtmlPreviewModal, toggleSidebar } from './modals.js';
|
| 7 |
import { createDeepThinkPanel, createReasoningPanel, hideDeepThinkPanel, hideReasoningPanel, updateDeepThinkPanel, updateReasoningPanel } from './tools.js';
|
| 8 |
|
| 9 |
export const PREMIUM_URL = '#/nav/online/news/getSingle/1149636/eyJpdiI6InZSVUdlLzBlR0FzOHZJdXFZeWhER0E9PSIsInZhbHVlIjoiWFhqRXBLc29vSFpHdk9nYmRjZGVuWHRHRHVSZHRlTG1BUENLaE5mNXBNVVRGWFg3ZWN0djJ5K1dIY1RqTHJGaCIsIm1hYyI6IjIzYzFlZTMwYmVmMTdkYjQ0YTQ4YWMxNmFhN2RmNWQ2OTc1NDIyNGVlZGI3ZjJjMjhkNmQxNjM4MDFlZTIxNmUiLCJ0YWciOiIifQ==/20934991';
|
|
@@ -183,6 +184,7 @@ export function setupCodeBlockActions(container) {
|
|
| 183 |
});
|
| 184 |
}
|
| 185 |
|
|
|
|
| 186 |
export function renderHistoryList() {
|
| 187 |
dom.historyList.innerHTML = '';
|
| 188 |
const chatsToDisplay = state.chatSessions.filter(session => session.messages.length > 0 || session.id === state.activeChatId);
|
|
@@ -190,17 +192,30 @@ export function renderHistoryList() {
|
|
| 190 |
chatsToDisplay.forEach((session) => {
|
| 191 |
const itemContainer = document.createElement('div');
|
| 192 |
itemContainer.className = 'history-item flex items-center justify-between rounded-lg';
|
|
|
|
| 193 |
const itemLink = document.createElement('a');
|
| 194 |
itemLink.href = '#';
|
| 195 |
itemLink.className = `flex-grow p-3 truncate transition-colors rounded-lg ${session.id === state.activeChatId ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 font-semibold' : 'hover:bg-slate-200/60 dark:hover:bg-slate-700/60 text-slate-700 dark:text-slate-300'}`;
|
| 196 |
itemLink.textContent = session.title;
|
| 197 |
-
itemLink.onclick = (e) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
const menuButton = document.createElement('button');
|
| 199 |
menuButton.className = 'history-item-button p-2 ml-1 text-slate-500 dark:text-slate-400 hover:bg-slate-200/80 dark:hover:bg-slate-700/80 rounded-full flex-shrink-0';
|
| 200 |
menuButton.innerHTML = '<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM12.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM18.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0z" /></svg>';
|
|
|
|
|
|
|
| 201 |
menuButton.onclick = (e) => {
|
| 202 |
-
|
|
|
|
|
|
|
| 203 |
};
|
|
|
|
| 204 |
itemContainer.appendChild(itemLink);
|
| 205 |
itemContainer.appendChild(menuButton);
|
| 206 |
dom.historyList.appendChild(itemContainer);
|
|
@@ -386,27 +401,22 @@ export async function addMessageToUI(message, index, options = {}, existingEleme
|
|
| 386 |
const textParts = parts.filter(p => p.text);
|
| 387 |
const fileParts = parts.filter(p => p.id);
|
| 388 |
|
| 389 |
-
// *** START: MODIFIED - منطق جدید و اصلاح شده برای نمایش فایل ***
|
| 390 |
const processedFileParts = await Promise.all(
|
| 391 |
fileParts.map(async (part) => {
|
| 392 |
-
// همیشه فایل را از IndexedDB بر اساس ID میخوانیم تا URL تازه بسازیم
|
| 393 |
if (part.id) {
|
| 394 |
try {
|
| 395 |
const file = await db.getFile(part.id);
|
| 396 |
if (file) {
|
| 397 |
const newBlobUrl = URL.createObjectURL(file);
|
| 398 |
-
// یک آبجکت جدید با URL تازه برای رندر برمیگردانیم
|
| 399 |
return { ...part, fileUrl: newBlobUrl, mimeType: file.type, name: file.name };
|
| 400 |
}
|
| 401 |
} catch (error) {
|
| 402 |
console.error(`Error retrieving file ${part.id} from DB:`, error);
|
| 403 |
}
|
| 404 |
}
|
| 405 |
-
// در صورت خطا یا نبودن ID، پارت اصلی را برمیگردانیم تا پیام خطا نمایش داده شود
|
| 406 |
return { ...part, fileUrl: null };
|
| 407 |
})
|
| 408 |
);
|
| 409 |
-
// *** END: MODIFIED ***
|
| 410 |
|
| 411 |
const fileHtml = processedFileParts.map(p => createFileContentHtml(p)).join('');
|
| 412 |
const textHtml = textParts.map(p => `<div class="whitespace-pre-wrap">${escapeHTML(p.text)}</div>`).join('');
|
|
@@ -750,3 +760,4 @@ export function finalizeFreeWsMessage(modelBubbleOuterDivElement, fullText) {
|
|
| 750 |
});
|
| 751 |
}
|
| 752 |
}
|
|
|
|
|
|
| 1 |
+
// --- START OF FILE chat.js ---
|
| 2 |
// static/js/ui/chat.js
|
| 3 |
|
| 4 |
import * as state from '../state.js';
|
| 5 |
import * as db from '../db.js';
|
| 6 |
import { dom } from './dom.js';
|
| 7 |
+
import { toggleHtmlPreviewModal, toggleSidebar, showHistoryMenu, showMessageMenu } from './modals.js'; // *** تغییر مهم: ایمپورت مستقیم ***
|
| 8 |
import { createDeepThinkPanel, createReasoningPanel, hideDeepThinkPanel, hideReasoningPanel, updateDeepThinkPanel, updateReasoningPanel } from './tools.js';
|
| 9 |
|
| 10 |
export const PREMIUM_URL = '#/nav/online/news/getSingle/1149636/eyJpdiI6InZSVUdlLzBlR0FzOHZJdXFZeWhER0E9PSIsInZhbHVlIjoiWFhqRXBLc29vSFpHdk9nYmRjZGVuWHRHRHVSZHRlTG1BUENLaE5mNXBNVVRGWFg3ZWN0djJ5K1dIY1RqTHJGaCIsIm1hYyI6IjIzYzFlZTMwYmVmMTdkYjQ0YTQ4YWMxNmFhN2RmNWQ2OTc1NDIyNGVlZGI3ZjJjMjhkNmQxNjM4MDFlZTIxNmUiLCJ0YWciOiIifQ==/20934991';
|
|
|
|
| 184 |
});
|
| 185 |
}
|
| 186 |
|
| 187 |
+
// *** تابع رندر لیست تاریخچه (اصلاح شده برای عملکرد صحیح دکمه منو) ***
|
| 188 |
export function renderHistoryList() {
|
| 189 |
dom.historyList.innerHTML = '';
|
| 190 |
const chatsToDisplay = state.chatSessions.filter(session => session.messages.length > 0 || session.id === state.activeChatId);
|
|
|
|
| 192 |
chatsToDisplay.forEach((session) => {
|
| 193 |
const itemContainer = document.createElement('div');
|
| 194 |
itemContainer.className = 'history-item flex items-center justify-between rounded-lg';
|
| 195 |
+
|
| 196 |
const itemLink = document.createElement('a');
|
| 197 |
itemLink.href = '#';
|
| 198 |
itemLink.className = `flex-grow p-3 truncate transition-colors rounded-lg ${session.id === state.activeChatId ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 font-semibold' : 'hover:bg-slate-200/60 dark:hover:bg-slate-700/60 text-slate-700 dark:text-slate-300'}`;
|
| 199 |
itemLink.textContent = session.title;
|
| 200 |
+
itemLink.onclick = (e) => {
|
| 201 |
+
e.preventDefault();
|
| 202 |
+
state.setActiveChatId(session.id);
|
| 203 |
+
renderActiveChat();
|
| 204 |
+
renderHistoryList();
|
| 205 |
+
toggleSidebar(false);
|
| 206 |
+
};
|
| 207 |
+
|
| 208 |
const menuButton = document.createElement('button');
|
| 209 |
menuButton.className = 'history-item-button p-2 ml-1 text-slate-500 dark:text-slate-400 hover:bg-slate-200/80 dark:hover:bg-slate-700/80 rounded-full flex-shrink-0';
|
| 210 |
menuButton.innerHTML = '<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM12.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0zM18.75 12a.75.75 0 11-1.5 0 .75.75 0 011.5 0z" /></svg>';
|
| 211 |
+
|
| 212 |
+
// *** تغییر اصلی: فراخوانی مستقیم تابع منو ***
|
| 213 |
menuButton.onclick = (e) => {
|
| 214 |
+
e.preventDefault();
|
| 215 |
+
e.stopPropagation();
|
| 216 |
+
showHistoryMenu(e, session.id);
|
| 217 |
};
|
| 218 |
+
|
| 219 |
itemContainer.appendChild(itemLink);
|
| 220 |
itemContainer.appendChild(menuButton);
|
| 221 |
dom.historyList.appendChild(itemContainer);
|
|
|
|
| 401 |
const textParts = parts.filter(p => p.text);
|
| 402 |
const fileParts = parts.filter(p => p.id);
|
| 403 |
|
|
|
|
| 404 |
const processedFileParts = await Promise.all(
|
| 405 |
fileParts.map(async (part) => {
|
|
|
|
| 406 |
if (part.id) {
|
| 407 |
try {
|
| 408 |
const file = await db.getFile(part.id);
|
| 409 |
if (file) {
|
| 410 |
const newBlobUrl = URL.createObjectURL(file);
|
|
|
|
| 411 |
return { ...part, fileUrl: newBlobUrl, mimeType: file.type, name: file.name };
|
| 412 |
}
|
| 413 |
} catch (error) {
|
| 414 |
console.error(`Error retrieving file ${part.id} from DB:`, error);
|
| 415 |
}
|
| 416 |
}
|
|
|
|
| 417 |
return { ...part, fileUrl: null };
|
| 418 |
})
|
| 419 |
);
|
|
|
|
| 420 |
|
| 421 |
const fileHtml = processedFileParts.map(p => createFileContentHtml(p)).join('');
|
| 422 |
const textHtml = textParts.map(p => `<div class="whitespace-pre-wrap">${escapeHTML(p.text)}</div>`).join('');
|
|
|
|
| 760 |
});
|
| 761 |
}
|
| 762 |
}
|
| 763 |
+
// --- END OF FILE chat.js ---
|