umar8902 commited on
Commit
f8871f2
·
verified ·
1 Parent(s): 2008baf

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +176 -10
index.html CHANGED
@@ -2242,6 +2242,68 @@
2242
  animation: spin 1s linear infinite;
2243
  }
2244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2245
  @keyframes bounce {
2246
 
2247
  0%,
@@ -4674,7 +4736,13 @@
4674
  </aside>
4675
 
4676
  <!-- Main Area -->
4677
- <main class="main-area hero-mode">
 
 
 
 
 
 
4678
  <div class="main-background-lighting">
4679
  <div class="ambient-glow glow-1"></div>
4680
  <div class="ambient-glow glow-2"></div>
@@ -5435,7 +5503,18 @@
5435
  activateFeature('video');
5436
  break;
5437
  case 'upload':
5438
- triggerUpload('Document');
 
 
 
 
 
 
 
 
 
 
 
5439
  return;
5440
  case 'voice':
5441
  toggleVoiceMode();
@@ -5881,6 +5960,83 @@
5881
  });
5882
  }
5883
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5884
  function setupEventListeners() {
5885
  // FIXED: Restructured with early returns to prevent fall-through bugs
5886
  document.addEventListener('click', (e) => {
@@ -6250,11 +6406,11 @@
6250
  container.appendChild(textContainer);
6251
  container.appendChild(cursor);
6252
 
6253
- // Process in chunks (roughly 2-3 words at a time) for a smoother "line-by-line" feel
6254
- for (let i = 0; i < words.length; i += 2) {
6255
  if (!isTyping) break;
6256
 
6257
- const chunk = words.slice(i, i + 2).join(' ');
6258
  const span = document.createElement('span');
6259
  span.className = 'streaming-text';
6260
  span.innerHTML = (i === 0 ? '' : ' ') + chunk;
@@ -6264,9 +6420,8 @@
6264
 
6265
  smoothScrollToBottom();
6266
 
6267
- // Faster, more natural delay
6268
- const delay = Math.floor(Math.random() * (40 - 15 + 1)) + 15;
6269
- await new Promise(resolve => setTimeout(resolve, delay));
6270
  }
6271
 
6272
  cursor.remove();
@@ -6311,8 +6466,14 @@
6311
  ];
6312
  let statusIdx = 0;
6313
 
 
 
6314
  messageContent.innerHTML = `
6315
  <div style="display:flex; flex-direction:column; align-items:flex-start; gap:12px; padding: 10px 0;">
 
 
 
 
6316
  <div class="ai-processing-ring">
6317
  <div class="blinking-emoji" style="width:24px; height:24px;">
6318
  <div class="eye" style="width:3px; height:5px;"></div>
@@ -6803,10 +6964,13 @@
6803
  const data = await response.json();
6804
 
6805
  if (data.results && data.results.length > 0) {
 
 
 
6806
  messageContent.innerHTML = `
6807
  <div class="tool-output-header">
6808
  <i data-lucide="search"></i>
6809
- <span>Sources Discovered</span>
6810
  </div>
6811
  <div class="search-results">
6812
  ${data.results.map(res => `
@@ -6818,7 +6982,7 @@
6818
  </div>
6819
  <div class="compiling-loader" id="compilingLoader">
6820
  <i data-lucide="loader-2"></i>
6821
- <span>Compiling synthesized research report...</span>
6822
  </div>
6823
  `;
6824
  if (window.lucide) lucide.createIcons();
@@ -7685,6 +7849,8 @@
7685
  }
7686
 
7687
  refreshIcons();
 
 
7688
  }
7689
 
7690
  // --- SPA Routing Logic ---
 
2242
  animation: spin 1s linear infinite;
2243
  }
2244
 
2245
+ /* Drag and Drop Overlay */
2246
+ .drag-drop-overlay {
2247
+ position: absolute;
2248
+ top: 0;
2249
+ left: 0;
2250
+ width: 100%;
2251
+ height: 100%;
2252
+ background: rgba(16, 163, 127, 0.15);
2253
+ backdrop-filter: blur(8px);
2254
+ border: 2px dashed var(--accent-blue);
2255
+ z-index: 500;
2256
+ display: none;
2257
+ align-items: center;
2258
+ justify-content: center;
2259
+ flex-direction: column;
2260
+ gap: 20px;
2261
+ pointer-events: none;
2262
+ transition: all 0.3s ease;
2263
+ }
2264
+
2265
+ .drag-drop-overlay.active {
2266
+ display: flex;
2267
+ animation: fadeIn 0.3s ease;
2268
+ }
2269
+
2270
+ .drag-drop-icon {
2271
+ width: 80px;
2272
+ height: 80px;
2273
+ background: rgba(16, 163, 127, 0.1);
2274
+ border-radius: 50%;
2275
+ display: flex;
2276
+ align-items: center;
2277
+ justify-content: center;
2278
+ color: var(--accent-blue);
2279
+ animation: pulse-glow 2s infinite;
2280
+ }
2281
+
2282
+ @keyframes pulse-glow {
2283
+ 0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 163, 127, 0.4); }
2284
+ 50% { transform: scale(1.1); box-shadow: 0 0 20px 10px rgba(16, 163, 127, 0); }
2285
+ }
2286
+
2287
+ .drag-drop-text {
2288
+ font-size: 24px;
2289
+ font-weight: 700;
2290
+ color: var(--text-primary);
2291
+ }
2292
+
2293
+ .llm-badge {
2294
+ display: inline-flex;
2295
+ align-items: center;
2296
+ gap: 6px;
2297
+ background: rgba(255, 255, 255, 0.05);
2298
+ border: 1px solid var(--border-color);
2299
+ padding: 4px 10px;
2300
+ border-radius: 8px;
2301
+ font-size: 11px;
2302
+ color: var(--text-secondary);
2303
+ font-weight: 600;
2304
+ margin-bottom: 8px;
2305
+ }
2306
+
2307
  @keyframes bounce {
2308
 
2309
  0%,
 
4736
  </aside>
4737
 
4738
  <!-- Main Area -->
4739
+ <main class="main-area hero-mode" id="mainArea">
4740
+ <div class="drag-drop-overlay" id="dragDropOverlay">
4741
+ <div class="drag-drop-icon">
4742
+ <i data-lucide="upload-cloud" style="width: 40px; height: 40px;"></i>
4743
+ </div>
4744
+ <div class="drag-drop-text">Drop files to upload to Nexa AI</div>
4745
+ </div>
4746
  <div class="main-background-lighting">
4747
  <div class="ambient-glow glow-1"></div>
4748
  <div class="ambient-glow glow-2"></div>
 
5503
  activateFeature('video');
5504
  break;
5505
  case 'upload':
5506
+ // Trigger hidden file input
5507
+ let fileInput = document.getElementById('hiddenFileInput');
5508
+ if (!fileInput) {
5509
+ fileInput = document.createElement('input');
5510
+ fileInput.type = 'file';
5511
+ fileInput.id = 'hiddenFileInput';
5512
+ fileInput.multiple = true;
5513
+ fileInput.style.display = 'none';
5514
+ fileInput.onchange = (e) => handleFiles(e.target.files);
5515
+ document.body.appendChild(fileInput);
5516
+ }
5517
+ fileInput.click();
5518
  return;
5519
  case 'voice':
5520
  toggleVoiceMode();
 
5960
  });
5961
  }
5962
 
5963
+ function setupDragAndDrop() {
5964
+ const mainArea = document.getElementById('mainArea');
5965
+ const overlay = document.getElementById('dragDropOverlay');
5966
+
5967
+ if (!mainArea || !overlay) return;
5968
+
5969
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
5970
+ mainArea.addEventListener(eventName, (e) => {
5971
+ e.preventDefault();
5972
+ e.stopPropagation();
5973
+ }, false);
5974
+ });
5975
+
5976
+ ['dragenter', 'dragover'].forEach(eventName => {
5977
+ mainArea.addEventListener(eventName, () => {
5978
+ overlay.classList.add('active');
5979
+ }, false);
5980
+ });
5981
+
5982
+ ['dragleave', 'drop'].forEach(eventName => {
5983
+ mainArea.addEventListener(eventName, () => {
5984
+ overlay.classList.remove('active');
5985
+ }, false);
5986
+ });
5987
+
5988
+ mainArea.addEventListener('drop', (e) => {
5989
+ const dt = e.dataTransfer;
5990
+ const files = dt.files;
5991
+ if (files && files.length > 0) {
5992
+ handleFiles(files);
5993
+ }
5994
+ }, false);
5995
+ }
5996
+
5997
+ function handleFiles(files) {
5998
+ const container = document.getElementById('attachmentsContainer');
5999
+ if (!container) return;
6000
+
6001
+ container.style.display = 'flex';
6002
+
6003
+ Array.from(files).forEach(file => {
6004
+ const card = document.createElement('div');
6005
+ card.className = 'file-attachment-card';
6006
+ card.setAttribute('data-filename', file.name);
6007
+
6008
+ const fileExt = file.name.split('.').pop().toUpperCase();
6009
+ let iconColor = '#3182ce'; // Default blue
6010
+ let iconName = 'file-text';
6011
+
6012
+ if (['JPG', 'JPEG', 'PNG', 'GIF', 'WEBP'].includes(fileExt)) {
6013
+ iconColor = '#10a37f';
6014
+ iconName = 'image';
6015
+ } else if (fileExt === 'PDF') {
6016
+ iconColor = '#e53e3e';
6017
+ iconName = 'file-text';
6018
+ }
6019
+
6020
+ card.innerHTML = `
6021
+ <div class="file-attachment-icon" style="background: ${iconColor}">
6022
+ <i data-lucide="${iconName}" style="width: 18px; height: 18px;"></i>
6023
+ </div>
6024
+ <div class="file-attachment-info">
6025
+ <span class="file-attachment-name">${file.name}</span>
6026
+ <span class="file-attachment-type">${fileExt} File</span>
6027
+ </div>
6028
+ <div class="file-attachment-remove" onclick="this.parentElement.remove(); if(document.getElementById('attachmentsContainer').children.length === 0) document.getElementById('attachmentsContainer').style.display='none';">
6029
+ <i data-lucide="x"></i>
6030
+ </div>
6031
+ `;
6032
+ container.appendChild(card);
6033
+ if (window.lucide) lucide.createIcons();
6034
+
6035
+ // Automatically start analysis if backend supports it
6036
+ handleFileAnalysis(file, card);
6037
+ });
6038
+ }
6039
+
6040
  function setupEventListeners() {
6041
  // FIXED: Restructured with early returns to prevent fall-through bugs
6042
  document.addEventListener('click', (e) => {
 
6406
  container.appendChild(textContainer);
6407
  container.appendChild(cursor);
6408
 
6409
+ // Optimized for maximum speed: Process in larger chunks with minimal delay
6410
+ for (let i = 0; i < words.length; i += 8) {
6411
  if (!isTyping) break;
6412
 
6413
+ const chunk = words.slice(i, i + 8).join(' ');
6414
  const span = document.createElement('span');
6415
  span.className = 'streaming-text';
6416
  span.innerHTML = (i === 0 ? '' : ' ') + chunk;
 
6420
 
6421
  smoothScrollToBottom();
6422
 
6423
+ // Minimum possible delay for ultra-fast "writing" effect
6424
+ await new Promise(resolve => setTimeout(resolve, 5));
 
6425
  }
6426
 
6427
  cursor.remove();
 
6466
  ];
6467
  let statusIdx = 0;
6468
 
6469
+ const modelLabel = currentAiModel || 'Qwen 2.5';
6470
+
6471
  messageContent.innerHTML = `
6472
  <div style="display:flex; flex-direction:column; align-items:flex-start; gap:12px; padding: 10px 0;">
6473
+ <div class="llm-badge">
6474
+ <i data-lucide="cpu" style="width:12px;"></i>
6475
+ <span>Using ${modelLabel}</span>
6476
+ </div>
6477
  <div class="ai-processing-ring">
6478
  <div class="blinking-emoji" style="width:24px; height:24px;">
6479
  <div class="eye" style="width:3px; height:5px;"></div>
 
6964
  const data = await response.json();
6965
 
6966
  if (data.results && data.results.length > 0) {
6967
+ const count = data.results.length;
6968
+ addMessage(`🔍 I found **${count} search results** related to your question. Let me visit the most relevant sources to gather accurate information.`, 'ai');
6969
+
6970
  messageContent.innerHTML = `
6971
  <div class="tool-output-header">
6972
  <i data-lucide="search"></i>
6973
+ <span>Intelligence Sources Discovered</span>
6974
  </div>
6975
  <div class="search-results">
6976
  ${data.results.map(res => `
 
6982
  </div>
6983
  <div class="compiling-loader" id="compilingLoader">
6984
  <i data-lucide="loader-2"></i>
6985
+ <span>Synthesizing verified research report...</span>
6986
  </div>
6987
  `;
6988
  if (window.lucide) lucide.createIcons();
 
7849
  }
7850
 
7851
  refreshIcons();
7852
+ setupEventListeners();
7853
+ setupDragAndDrop();
7854
  }
7855
 
7856
  // --- SPA Routing Logic ---