Fuckingbase commited on
Commit
b126a82
·
verified ·
1 Parent(s): b3f3b04

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +107 -21
index.html CHANGED
@@ -340,36 +340,130 @@ class RobotFace {
340
  this.blinkProgress = 1; this.isBlinking = false; this.lastBlinkTime = Date.now();
341
  this.isSleeping = true; this.lastInteractionTime = Date.now(); this.sleepTimeout = 10000;
342
  this.isWatchingInput = false; this.isThinking = false;
343
- this.readingOscillation = 0; this.thinkingInterval = null;
 
 
 
 
 
 
 
 
 
 
 
 
344
  this.initInteractions(); requestAnimationFrame(this.render.bind(this));
345
  }
 
346
  render() {
347
  this.lookX += (this.targetLookX - this.lookX) * 0.1;
348
  this.lookY += (this.targetLookY - this.lookY) * 0.1;
349
  this.ctx.clearRect(0, 0, this.W, this.H); this.drawFaceplate();
350
  const now = Date.now();
351
- if (this.isSleeping) { this.drawSleepEyes(); } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  if (this.isWatchingInput) {
353
  this.targetLookY = 25; this.readingOscillation += 0.1;
354
  this.targetLookX = Math.sin(this.readingOscillation) * 10;
355
  }
356
- if (!this.isThinking && !this.isWatchingInput && now - this.lastInteractionTime > this.sleepTimeout) { this.isSleeping = true; }
357
- if (!this.isBlinking && !this.isThinking && now - this.lastBlinkTime > 3000 + Math.random() * 2000) { this.blink(); }
 
 
 
358
  this.drawExpression();
359
  }
360
  requestAnimationFrame(this.render.bind(this));
361
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
362
  drawFaceplate() {
363
  const c = this.ctx, r = 60;
364
  c.fillStyle = '#050505'; c.strokeStyle = '#333333'; c.lineWidth = 4;
365
  c.beginPath(); c.roundRect(0, 0, this.W, this.H, r); c.fill(); c.stroke();
366
  }
367
- drawExpression() {
368
- const eW = 100, eH = 100, eR = 30, eY = this.H / 2 + this.lookY;
369
- const lCX = this.W * 0.3 + this.lookX, rCX = this.W * 0.7 + this.lookX;
370
- const cH = eH * this.blinkProgress;
371
- this.drawEye(lCX, eY, eW, cH, eR); this.drawEye(rCX, eY, eW, cH, eR);
372
- }
373
  drawEye(cx, cy, w, h, r) {
374
  const c = this.ctx;
375
  const eyeColor = getComputedStyle(document.documentElement).getPropertyValue('--eye-color').trim();
@@ -420,11 +514,6 @@ class RobotFace {
420
  };
421
  requestAnimationFrame(a);
422
  }
423
- startThinking() {
424
- this.isThinking = true; this.targetLookX = 0; this.targetLookY = 0;
425
- this.thinkingInterval = setInterval(() => this.blink(), 800);
426
- }
427
- stopThinking() { this.isThinking = false; clearInterval(this.thinkingInterval); }
428
  }
429
 
430
  class ChatInterface {
@@ -435,7 +524,7 @@ class ChatInterface {
435
  this.inputArea = document.getElementById('input-area');
436
  this.sendButtonContainer = document.getElementById('send-button-container');
437
  this.sendButton = document.getElementById('send-button');
438
- this.isDragging = false; this.startY = 0; this.currentY = 0; this.dragThreshold = 30; // اصلاح آستانه
439
  this.API_URL = 'https://text.pollinations.ai/openai';
440
 
441
  const SYSTEM_PROMPT = `
@@ -572,20 +661,17 @@ class ChatInterface {
572
  return '';
573
  });
574
 
575
- // First, escape all HTML, then process markdown.
576
  let contentHtml = escapeHTML(processedText)
577
  .replace(markdownLinkRegex, '<a href="$2" target="_blank">$1</a>');
578
 
579
- // Since code blocks are special, we handle them separately to avoid double-escaping.
580
  contentHtml = contentHtml.replace(codeBlockRegex, (match, lang, code) => {
581
  const uniqueId = `code-${Date.now()}-${Math.random()}`;
582
- // The code inside is already escaped from the main escapeHTML call.
583
- return `<div class="code-block-wrapper">
584
  <div class="code-block-header">
585
  <button class="copy-code-btn" data-target="${uniqueId}">کپی</button>
586
  </div>
587
  <pre><code id="${uniqueId}">${code.trim()}</code></pre>
588
- </div>`;
589
  });
590
 
591
  bubble.innerHTML = `
 
340
  this.blinkProgress = 1; this.isBlinking = false; this.lastBlinkTime = Date.now();
341
  this.isSleeping = true; this.lastInteractionTime = Date.now(); this.sleepTimeout = 10000;
342
  this.isWatchingInput = false; this.isThinking = false;
343
+ this.readingOscillation = 0;
344
+
345
+ // --- State variables for new animations ---
346
+ this.thinkingStartTime = 0;
347
+ this.leftEyeScale = 1;
348
+ this.rightEyeScale = 1;
349
+
350
+ this.isFocusing = false;
351
+ this.focusProgress = 0;
352
+ this.focusEye = 'left';
353
+ this.lastFocusTime = Date.now();
354
+ this.nextFocusDelay = 4000 + Math.random() * 3000;
355
+
356
  this.initInteractions(); requestAnimationFrame(this.render.bind(this));
357
  }
358
+
359
  render() {
360
  this.lookX += (this.targetLookX - this.lookX) * 0.1;
361
  this.lookY += (this.targetLookY - this.lookY) * 0.1;
362
  this.ctx.clearRect(0, 0, this.W, this.H); this.drawFaceplate();
363
  const now = Date.now();
364
+
365
+ if (this.isSleeping) {
366
+ this.drawSleepEyes();
367
+ } else {
368
+ // --- Animation Logic ---
369
+ const isIdle = !this.isThinking && !this.isWatchingInput && !this.isBlinking && !this.isFocusing;
370
+
371
+ if (this.isThinking) {
372
+ const elapsed = now - this.thinkingStartTime;
373
+ const oscillation = Math.sin(elapsed / 300); // Speed of thinking animation
374
+ const scaleAmount = 0.3; // How much the eye scales
375
+ this.leftEyeScale = 1 - (scaleAmount * (oscillation + 1) / 2);
376
+ this.rightEyeScale = 1 - (scaleAmount * (-oscillation + 1) / 2);
377
+ } else {
378
+ // Reset scale if not thinking
379
+ this.leftEyeScale = 1;
380
+ this.rightEyeScale = 1;
381
+ }
382
+
383
  if (this.isWatchingInput) {
384
  this.targetLookY = 25; this.readingOscillation += 0.1;
385
  this.targetLookX = Math.sin(this.readingOscillation) * 10;
386
  }
387
+
388
+ if (isIdle && now - this.lastInteractionTime > this.sleepTimeout) { this.isSleeping = true; }
389
+ if (isIdle && now - this.lastBlinkTime > 3000 + Math.random() * 2000) { this.blink(); }
390
+ if (isIdle && now - this.lastFocusTime > this.nextFocusDelay) { this.startFocus(); }
391
+
392
  this.drawExpression();
393
  }
394
  requestAnimationFrame(this.render.bind(this));
395
  }
396
+
397
+ drawExpression() {
398
+ const eW = 100, eH = 100, eR = 30, eY = this.H / 2 + this.lookY;
399
+ const lCX = this.W * 0.3 + this.lookX, rCX = this.W * 0.7 + this.lookX;
400
+
401
+ let finalLeftScale = this.leftEyeScale;
402
+ let finalRightScale = this.rightEyeScale;
403
+
404
+ if (this.isFocusing) {
405
+ const scale = 1 - (1 - 0.65) * this.focusProgress;
406
+ if (this.focusEye === 'left') {
407
+ finalLeftScale = scale;
408
+ } else {
409
+ finalRightScale = scale;
410
+ }
411
+ }
412
+
413
+ const lW = eW * finalLeftScale;
414
+ const lH = eH * this.blinkProgress * finalLeftScale;
415
+ const rW = eW * finalRightScale;
416
+ const rH = eH * this.blinkProgress * finalRightScale;
417
+
418
+ this.drawEye(lCX, eY, lW, lH, eR);
419
+ this.drawEye(rCX, eY, rW, rH, eR);
420
+ }
421
+
422
+ startFocus() {
423
+ if (this.isFocusing) return;
424
+ this.isFocusing = true;
425
+ this.focusEye = Math.random() < 0.5 ? 'left' : 'right';
426
+ this.lastFocusTime = Date.now();
427
+ this.nextFocusDelay = 4000 + Math.random() * 3000;
428
+
429
+ let startTime = null;
430
+ const duration = 300; // a quick focus animation
431
+ const animateFocus = (timestamp) => {
432
+ if (!startTime) startTime = timestamp;
433
+ const elapsed = timestamp - startTime;
434
+
435
+ if (elapsed < duration) { // Focusing in
436
+ this.focusProgress = elapsed / duration;
437
+ } else if (elapsed < duration * 2) { // Focusing out
438
+ this.focusProgress = 1 - ((elapsed - duration) / duration);
439
+ } else {
440
+ this.focusProgress = 0;
441
+ this.isFocusing = false;
442
+ return;
443
+ }
444
+ requestAnimationFrame(animateFocus);
445
+ };
446
+ requestAnimationFrame(animateFocus);
447
+ }
448
+
449
+ startThinking() {
450
+ this.isThinking = true;
451
+ this.thinkingStartTime = Date.now();
452
+ this.targetLookX = 0; this.targetLookY = 0;
453
+ }
454
+
455
+ stopThinking() {
456
+ this.isThinking = false;
457
+ this.leftEyeScale = 1;
458
+ this.rightEyeScale = 1;
459
+ }
460
+
461
+ // --- Other methods (drawFaceplate, drawEye, drawSleepEyes, initInteractions, wakeUp, blink) remain unchanged ---
462
  drawFaceplate() {
463
  const c = this.ctx, r = 60;
464
  c.fillStyle = '#050505'; c.strokeStyle = '#333333'; c.lineWidth = 4;
465
  c.beginPath(); c.roundRect(0, 0, this.W, this.H, r); c.fill(); c.stroke();
466
  }
 
 
 
 
 
 
467
  drawEye(cx, cy, w, h, r) {
468
  const c = this.ctx;
469
  const eyeColor = getComputedStyle(document.documentElement).getPropertyValue('--eye-color').trim();
 
514
  };
515
  requestAnimationFrame(a);
516
  }
 
 
 
 
 
517
  }
518
 
519
  class ChatInterface {
 
524
  this.inputArea = document.getElementById('input-area');
525
  this.sendButtonContainer = document.getElementById('send-button-container');
526
  this.sendButton = document.getElementById('send-button');
527
+ this.isDragging = false; this.startY = 0; this.currentY = 0; this.dragThreshold = 30;
528
  this.API_URL = 'https://text.pollinations.ai/openai';
529
 
530
  const SYSTEM_PROMPT = `
 
661
  return '';
662
  });
663
 
 
664
  let contentHtml = escapeHTML(processedText)
665
  .replace(markdownLinkRegex, '<a href="$2" target="_blank">$1</a>');
666
 
 
667
  contentHtml = contentHtml.replace(codeBlockRegex, (match, lang, code) => {
668
  const uniqueId = `code-${Date.now()}-${Math.random()}`;
669
+ return `</div><div class="code-block-wrapper">
 
670
  <div class="code-block-header">
671
  <button class="copy-code-btn" data-target="${uniqueId}">کپی</button>
672
  </div>
673
  <pre><code id="${uniqueId}">${code.trim()}</code></pre>
674
+ </div><div class="message-content">`;
675
  });
676
 
677
  bubble.innerHTML = `