Spaces:
Running
Running
Update index.html
Browse files- index.html +74 -13
index.html
CHANGED
|
@@ -114,6 +114,14 @@
|
|
| 114 |
.message-content {
|
| 115 |
padding: 10px 15px; border-radius: 20px;
|
| 116 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
@keyframes popIn { to { opacity: 1; transform: translateY(0); } }
|
| 119 |
|
|
@@ -223,12 +231,43 @@
|
|
| 223 |
width: 50px; height: 90px; background-color: #111;
|
| 224 |
border-radius: 25px; margin-left: 10px; position: relative;
|
| 225 |
overflow: hidden; display: flex; justify-content: center;
|
| 226 |
-
align-items:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
}
|
| 228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
#send-button {
|
| 230 |
width: 40px; height: 40px; background-color: var(--eye-color);
|
| 231 |
-
border-radius: 50%; position: absolute; top:
|
| 232 |
display: flex; justify-content: center; align-items: center;
|
| 233 |
transition: top 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
| 234 |
}
|
|
@@ -279,7 +318,7 @@
|
|
| 279 |
<div id="input-area">
|
| 280 |
<div id="send-button-container">
|
| 281 |
<div id="send-button">
|
| 282 |
-
<svg viewBox="0 0 24 24" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M12
|
| 283 |
</div>
|
| 284 |
</div>
|
| 285 |
<textarea id="message-input" placeholder="بگو ببینم دیگه چی میخوای !؟" rows="1"></textarea>
|
|
@@ -396,9 +435,10 @@ class ChatInterface {
|
|
| 396 |
this.robotFace = robotFace;
|
| 397 |
this.chatContainer = document.getElementById('chat-container');
|
| 398 |
this.input = document.getElementById('message-input');
|
|
|
|
| 399 |
this.sendButtonContainer = document.getElementById('send-button-container');
|
| 400 |
this.sendButton = document.getElementById('send-button');
|
| 401 |
-
this.isDragging = false; this.startY = 0; this.currentY = 0; this.dragThreshold =
|
| 402 |
this.API_URL = 'https://text.pollinations.ai/openai';
|
| 403 |
|
| 404 |
const SYSTEM_PROMPT = `
|
|
@@ -433,7 +473,15 @@ class ChatInterface {
|
|
| 433 |
}
|
| 434 |
|
| 435 |
initListeners() {
|
| 436 |
-
this.input.addEventListener('input', () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
this.input.addEventListener('focus', () => {
|
| 438 |
this.robotFace.isWatchingInput = true; this.robotFace.wakeUp();
|
| 439 |
setTimeout(() => { document.getElementById('input-area').scrollIntoView({ behavior: 'smooth', block: 'end' }); }, 300);
|
|
@@ -456,16 +504,17 @@ class ChatInterface {
|
|
| 456 |
if (!this.isDragging) return; e.preventDefault();
|
| 457 |
const y = e.pageY || e.touches?.[0]?.pageY;
|
| 458 |
let diff = y - this.startY; if (diff < 0) diff = 0;
|
| 459 |
-
const maxDrag = this.sendButtonContainer.offsetHeight - this.sendButton.offsetHeight -
|
| 460 |
if (diff > maxDrag) diff = maxDrag;
|
| 461 |
-
this.currentY = diff;
|
|
|
|
| 462 |
}
|
| 463 |
dragEnd() {
|
| 464 |
if (!this.isDragging) return;
|
| 465 |
this.isDragging = false; this.sendButton.classList.remove('dragging');
|
| 466 |
this.sendButtonContainer.style.cursor = 'grab';
|
| 467 |
if (this.currentY > this.dragThreshold) { this.sendMessage(this.input.value); }
|
| 468 |
-
this.sendButton.style.top = '
|
| 469 |
}
|
| 470 |
|
| 471 |
async sendMessage(messageText) {
|
|
@@ -475,6 +524,7 @@ class ChatInterface {
|
|
| 475 |
this.addMessage(text, 'user');
|
| 476 |
this.conversationHistory.push({ role: 'user', content: text });
|
| 477 |
this.input.value = ''; this.input.style.height = 'auto';
|
|
|
|
| 478 |
|
| 479 |
this.robotFace.startThinking();
|
| 480 |
const thinkingBubble = this.addMessage('...', 'bot', true);
|
|
@@ -517,25 +567,36 @@ class ChatInterface {
|
|
| 517 |
|
| 518 |
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
| 519 |
const buttonRegex = /\[button:(.*?)\]/g;
|
|
|
|
| 520 |
let buttonsHtml = '';
|
| 521 |
|
| 522 |
-
|
| 523 |
buttonsHtml += `<button class="chat-button">${escapeHTML(buttonText.trim())}</button>`;
|
| 524 |
return '';
|
| 525 |
});
|
| 526 |
|
| 527 |
-
let contentHtml =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
const uniqueId = `code-${Date.now()}-${Math.random()}`;
|
| 529 |
-
return
|
| 530 |
<div class="code-block-header">
|
| 531 |
<button class="copy-code-btn" data-target="${uniqueId}">کپی</button>
|
| 532 |
</div>
|
| 533 |
<pre><code id="${uniqueId}">${escapeHTML(code.trim())}</code></pre>
|
| 534 |
-
</div>`;
|
| 535 |
});
|
| 536 |
|
| 537 |
bubble.innerHTML = `
|
| 538 |
-
<div class="message-content">${
|
| 539 |
${buttonsHtml ? `<div class="interactive-buttons">${buttonsHtml}</div>` : ''}
|
| 540 |
`;
|
| 541 |
|
|
|
|
| 114 |
.message-content {
|
| 115 |
padding: 10px 15px; border-radius: 20px;
|
| 116 |
}
|
| 117 |
+
.message-content a {
|
| 118 |
+
color: var(--eye-color);
|
| 119 |
+
text-decoration: none;
|
| 120 |
+
font-weight: 500;
|
| 121 |
+
}
|
| 122 |
+
.message-content a:hover {
|
| 123 |
+
text-decoration: underline;
|
| 124 |
+
}
|
| 125 |
|
| 126 |
@keyframes popIn { to { opacity: 1; transform: translateY(0); } }
|
| 127 |
|
|
|
|
| 231 |
width: 50px; height: 90px; background-color: #111;
|
| 232 |
border-radius: 25px; margin-left: 10px; position: relative;
|
| 233 |
overflow: hidden; display: flex; justify-content: center;
|
| 234 |
+
align-items: flex-start;
|
| 235 |
+
cursor: grab;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
/* --- انیمیشن جدید راهنما --- */
|
| 239 |
+
#send-button-container::after {
|
| 240 |
+
content: '';
|
| 241 |
+
position: absolute;
|
| 242 |
+
left: 50%;
|
| 243 |
+
transform: translateX(-50%);
|
| 244 |
+
width: 70%;
|
| 245 |
+
height: 4px;
|
| 246 |
+
background: var(--eye-color);
|
| 247 |
+
border-radius: 4px;
|
| 248 |
+
box-shadow: 0 0 8px var(--eye-color), 0 0 16px var(--eye-color);
|
| 249 |
+
top: -20px;
|
| 250 |
+
opacity: 0;
|
| 251 |
+
animation: swipe-glow 2.5s ease-in-out infinite;
|
| 252 |
+
animation-delay: 1s;
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
#input-area.typing #send-button-container::after {
|
| 256 |
+
animation: none;
|
| 257 |
+
display: none;
|
| 258 |
}
|
| 259 |
|
| 260 |
+
@keyframes swipe-glow {
|
| 261 |
+
0% { top: 10px; opacity: 0; }
|
| 262 |
+
40% { opacity: 0.7; }
|
| 263 |
+
80% { top: 70px; opacity: 0; }
|
| 264 |
+
100% { top: 70px; opacity: 0; }
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
|
| 268 |
#send-button {
|
| 269 |
width: 40px; height: 40px; background-color: var(--eye-color);
|
| 270 |
+
border-radius: 50%; position: absolute; top: 10px;
|
| 271 |
display: flex; justify-content: center; align-items: center;
|
| 272 |
transition: top 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
| 273 |
}
|
|
|
|
| 318 |
<div id="input-area">
|
| 319 |
<div id="send-button-container">
|
| 320 |
<div id="send-button">
|
| 321 |
+
<svg viewBox="0 0 24 24" fill="none" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14m7-7l-7 7-7-7"/></svg>
|
| 322 |
</div>
|
| 323 |
</div>
|
| 324 |
<textarea id="message-input" placeholder="بگو ببینم دیگه چی میخوای !؟" rows="1"></textarea>
|
|
|
|
| 435 |
this.robotFace = robotFace;
|
| 436 |
this.chatContainer = document.getElementById('chat-container');
|
| 437 |
this.input = document.getElementById('message-input');
|
| 438 |
+
this.inputArea = document.getElementById('input-area');
|
| 439 |
this.sendButtonContainer = document.getElementById('send-button-container');
|
| 440 |
this.sendButton = document.getElementById('send-button');
|
| 441 |
+
this.isDragging = false; this.startY = 0; this.currentY = 0; this.dragThreshold = 50;
|
| 442 |
this.API_URL = 'https://text.pollinations.ai/openai';
|
| 443 |
|
| 444 |
const SYSTEM_PROMPT = `
|
|
|
|
| 473 |
}
|
| 474 |
|
| 475 |
initListeners() {
|
| 476 |
+
this.input.addEventListener('input', () => {
|
| 477 |
+
this.input.style.height = 'auto';
|
| 478 |
+
this.input.style.height = (this.input.scrollHeight) + 'px';
|
| 479 |
+
if (this.input.value.trim() !== '') {
|
| 480 |
+
this.inputArea.classList.add('typing');
|
| 481 |
+
} else {
|
| 482 |
+
this.inputArea.classList.remove('typing');
|
| 483 |
+
}
|
| 484 |
+
});
|
| 485 |
this.input.addEventListener('focus', () => {
|
| 486 |
this.robotFace.isWatchingInput = true; this.robotFace.wakeUp();
|
| 487 |
setTimeout(() => { document.getElementById('input-area').scrollIntoView({ behavior: 'smooth', block: 'end' }); }, 300);
|
|
|
|
| 504 |
if (!this.isDragging) return; e.preventDefault();
|
| 505 |
const y = e.pageY || e.touches?.[0]?.pageY;
|
| 506 |
let diff = y - this.startY; if (diff < 0) diff = 0;
|
| 507 |
+
const maxDrag = this.sendButtonContainer.offsetHeight - this.sendButton.offsetHeight - 5;
|
| 508 |
if (diff > maxDrag) diff = maxDrag;
|
| 509 |
+
this.currentY = diff;
|
| 510 |
+
this.sendButton.style.top = `${10 + this.currentY}px`;
|
| 511 |
}
|
| 512 |
dragEnd() {
|
| 513 |
if (!this.isDragging) return;
|
| 514 |
this.isDragging = false; this.sendButton.classList.remove('dragging');
|
| 515 |
this.sendButtonContainer.style.cursor = 'grab';
|
| 516 |
if (this.currentY > this.dragThreshold) { this.sendMessage(this.input.value); }
|
| 517 |
+
this.sendButton.style.top = '10px'; this.currentY = 0;
|
| 518 |
}
|
| 519 |
|
| 520 |
async sendMessage(messageText) {
|
|
|
|
| 524 |
this.addMessage(text, 'user');
|
| 525 |
this.conversationHistory.push({ role: 'user', content: text });
|
| 526 |
this.input.value = ''; this.input.style.height = 'auto';
|
| 527 |
+
this.inputArea.classList.remove('typing');
|
| 528 |
|
| 529 |
this.robotFace.startThinking();
|
| 530 |
const thinkingBubble = this.addMessage('...', 'bot', true);
|
|
|
|
| 567 |
|
| 568 |
const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
|
| 569 |
const buttonRegex = /\[button:(.*?)\]/g;
|
| 570 |
+
const markdownLinkRegex = /\[(.*?)\]\((.*?)\)/g;
|
| 571 |
let buttonsHtml = '';
|
| 572 |
|
| 573 |
+
let processedText = text.replace(buttonRegex, (match, buttonText) => {
|
| 574 |
buttonsHtml += `<button class="chat-button">${escapeHTML(buttonText.trim())}</button>`;
|
| 575 |
return '';
|
| 576 |
});
|
| 577 |
|
| 578 |
+
let contentHtml = '';
|
| 579 |
+
let lastIndex = 0;
|
| 580 |
+
|
| 581 |
+
// Create a temporary container to parse the text and handle nested elements
|
| 582 |
+
const tempDiv = document.createElement('div');
|
| 583 |
+
tempDiv.innerText = processedText; // Safely set text content first
|
| 584 |
+
|
| 585 |
+
// Now process for links and code blocks
|
| 586 |
+
let processedHtml = tempDiv.innerHTML.replace(markdownLinkRegex, '<a href="$2" target="_blank">$1</a>');
|
| 587 |
+
|
| 588 |
+
processedHtml = processedHtml.replace(codeBlockRegex, (match, lang, code) => {
|
| 589 |
const uniqueId = `code-${Date.now()}-${Math.random()}`;
|
| 590 |
+
return `</div><div class="code-block-wrapper">
|
| 591 |
<div class="code-block-header">
|
| 592 |
<button class="copy-code-btn" data-target="${uniqueId}">کپی</button>
|
| 593 |
</div>
|
| 594 |
<pre><code id="${uniqueId}">${escapeHTML(code.trim())}</code></pre>
|
| 595 |
+
</div><div class="message-content">`;
|
| 596 |
});
|
| 597 |
|
| 598 |
bubble.innerHTML = `
|
| 599 |
+
<div class="message-content">${processedHtml.trim()}</div>
|
| 600 |
${buttonsHtml ? `<div class="interactive-buttons">${buttonsHtml}</div>` : ''}
|
| 601 |
`;
|
| 602 |
|