umar8902 commited on
Commit
0da69e0
·
verified ·
1 Parent(s): e317af7

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +103 -101
index.html CHANGED
@@ -273,9 +273,27 @@
273
  --accent-glow: 0 0 20px rgba(16, 163, 127, 0.2);
274
  }
275
 
276
- .chat-history {
277
- gap: 40px; /* More breathing room */
278
- scroll-behavior: smooth;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  }
280
 
281
  /* Message Entrance Animation */
@@ -4514,9 +4532,7 @@
4514
  <div class="input-container-bottom" id="inputBottomRow">
4515
  <div class="input-actions-left">
4516
  <button class="action-btn" id="uploadBtn" onclick="toggleUploadMenu()">
4517
- <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4518
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
4519
- </svg>
4520
  </button>
4521
  <div class="upload-menu" id="uploadMenu">
4522
  <div class="tool-btn" data-action="search" title="Web Search">
@@ -4598,14 +4614,10 @@
4598
  </button>
4599
  <!-- FIXED: Removed inline onclick to prevent double-firing and used consistent SVG icons -->
4600
  <button class="send-button" id="sendBtn" title="Send message (Enter)">
4601
- <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4602
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18" />
4603
- </svg>
4604
  </button>
4605
  <button class="stop-button" id="stopBtn" title="Stop generating (Esc)">
4606
- <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4607
- <rect x="6" y="6" width="12" height="12" rx="2" fill="currentColor" />
4608
- </svg>
4609
  </button>
4610
  </div>
4611
  </div>
@@ -4809,6 +4821,10 @@
4809
  <span id="authToggleText">Don't have an account?</span>
4810
  <span class="auth-toggle" id="authToggleBtn" onclick="toggleAuthMode()">Sign Up</span>
4811
  </div>
 
 
 
 
4812
  </div>
4813
  </div>
4814
 
@@ -6051,95 +6067,6 @@
6051
  const thinkingDiv = showThinking();
6052
  const messageContent = thinkingDiv.querySelector('.message-content');
6053
 
6054
- // Check for video generation intent
6055
- const videoKeywords = ['generate video', 'create video', 'make a video', 'video about'];
6056
- const isVideoRequest = videoKeywords.some(k => query.toLowerCase().includes(k));
6057
-
6058
- if (isVideoRequest) {
6059
- messageContent.innerHTML = `
6060
- <div style="display:flex; align-items:center; gap:10px;">
6061
- <div class="thinking"><span></span><span></span><span></span></div>
6062
- <span style="font-size:13px; color:var(--text-secondary); font-weight:500;">Imagining your video...</span>
6063
- </div>
6064
- `;
6065
- smoothScrollToBottom();
6066
-
6067
- try {
6068
- const response = await fetch('/api/video/generate', {
6069
- method: 'POST',
6070
- headers: { 'Content-Type': 'application/json' },
6071
- body: JSON.stringify({ prompt: query })
6072
- });
6073
- const data = await response.json();
6074
-
6075
- if (data.status === 'success') {
6076
- hideThinking(thinkingDiv);
6077
- addMessage(`I've generated a video based on your request: "${query}"`, 'ai');
6078
-
6079
- const lastMsg = chatHistory.lastElementChild;
6080
- const msgContent = lastMsg.querySelector('.message-content');
6081
- const videoCard = document.createElement('div');
6082
- videoCard.className = 'image-card';
6083
- const videoId = 'vid-' + Date.now();
6084
-
6085
- if (data.is_motion_image) {
6086
- videoCard.innerHTML = `
6087
- <div class="video-container" style="background:none; position: relative;">
6088
- <img src="${data.video_url}" alt="${query}" class="motion-image" style="width:100%; border-radius:12px; display:block;">
6089
- <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,0.5); border-radius: 50%; width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; pointer-events: none;">
6090
- <i data-lucide="play" style="width: 30px; height: 30px; color: white; fill: white;"></i>
6091
- </div>
6092
- </div>
6093
- <div class="image-card-actions">
6094
- <a href="${data.video_url}" class="img-btn" onclick="downloadImage(event, '${data.video_url}')"><i data-lucide="download"></i> Download</a>
6095
- <button class="img-btn" onclick="openVideoOverlayModal('${data.video_url}')"><i data-lucide="type"></i> Add Text</button>
6096
- </div>
6097
- `;
6098
- } else {
6099
- videoCard.innerHTML = `
6100
- <div class="video-container" id="${videoId}-container">
6101
- <video id="${videoId}" autoplay loop muted playsinline>
6102
- <source src="${data.video_url}" type="video/mp4">
6103
- </video>
6104
- <div class="custom-video-controls">
6105
- <button class="vid-ctrl-btn play-pause">
6106
- <i data-lucide="pause"></i>
6107
- </button>
6108
- <div class="video-progress">
6109
- <div class="video-progress-filled"></div>
6110
- </div>
6111
- <div class="volume-container">
6112
- <button class="vid-ctrl-btn volume-btn">
6113
- <i data-lucide="volume-x"></i>
6114
- </button>
6115
- <div class="volume-slider-vertical">
6116
- <input type="range" min="0" max="1" step="0.1" value="0">
6117
- </div>
6118
- </div>
6119
- </div>
6120
- </div>
6121
- <div class="image-card-actions">
6122
- <a href="${data.video_url}" download class="img-btn"><i data-lucide="download"></i> Download Video</a>
6123
- <button class="img-btn" onclick="openVideoOverlayModal('${data.video_url}')"><i data-lucide="type"></i> Add Text</button>
6124
- </div>
6125
- `;
6126
- }
6127
- msgContent.appendChild(videoCard);
6128
- if (window.lucide) lucide.createIcons();
6129
- if (!data.is_motion_image) initCustomVideoPlayer(videoId);
6130
- smoothScrollToBottom();
6131
- return;
6132
- } else {
6133
- throw new Error(data.error);
6134
- }
6135
- } catch (err) {
6136
- console.error("Video generation failed:", err);
6137
- hideThinking(thinkingDiv);
6138
- addMessage(err.message, 'ai');
6139
- return;
6140
- }
6141
- }
6142
-
6143
  // Task 15: Stream the AI response normally (backend handles tool detection)
6144
  addMessage(query, 'user');
6145
 
@@ -6183,6 +6110,12 @@
6183
  if (!line.trim()) continue;
6184
  try {
6185
  const data = JSON.parse(line);
 
 
 
 
 
 
6186
 
6187
  // Task: Handle search results from backend synthesis
6188
  if (data.search_results) {
@@ -6244,6 +6177,75 @@
6244
  const badge = (toolsUsed.includes('search')) ? '<div class="compiled-search-badge"><i data-lucide="brain"></i> Synthesized Research Report</div>' : '';
6245
  aiContentEl.innerHTML = badge + marked.parse(fullResponse);
6246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6247
  // If backend used image tool, call image API and append to message
6248
  if (toolsUsed.includes('image')) {
6249
  const imageContainer = document.createElement('div');
 
273
  --accent-glow: 0 0 20px rgba(16, 163, 127, 0.2);
274
  }
275
 
276
+ .image-card, .tool-output-card {
277
+ min-height: 100px;
278
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
279
+ contain: content;
280
+ }
281
+
282
+ .img-skeleton {
283
+ background: linear-gradient(90deg, rgba(255,255,255,0.03) 25%, rgba(255,255,255,0.08) 50%, rgba(255,255,255,0.03) 75%);
284
+ background-size: 200% 100%;
285
+ animation: skeleton-loading 1.5s infinite;
286
+ }
287
+
288
+ @keyframes skeleton-loading {
289
+ 0% { background-position: 200% 0; }
290
+ 100% { background-position: -200% 0; }
291
+ }
292
+
293
+ /* Fix for layout shift in chat history */
294
+ .message-content {
295
+ min-width: 0;
296
+ overflow-wrap: break-word;
297
  }
298
 
299
  /* Message Entrance Animation */
 
4532
  <div class="input-container-bottom" id="inputBottomRow">
4533
  <div class="input-actions-left">
4534
  <button class="action-btn" id="uploadBtn" onclick="toggleUploadMenu()">
4535
+ <i data-lucide="plus"></i>
 
 
4536
  </button>
4537
  <div class="upload-menu" id="uploadMenu">
4538
  <div class="tool-btn" data-action="search" title="Web Search">
 
4614
  </button>
4615
  <!-- FIXED: Removed inline onclick to prevent double-firing and used consistent SVG icons -->
4616
  <button class="send-button" id="sendBtn" title="Send message (Enter)">
4617
+ <i data-lucide="arrow-up"></i>
 
 
4618
  </button>
4619
  <button class="stop-button" id="stopBtn" title="Stop generating (Esc)">
4620
+ <i data-lucide="square"></i>
 
 
4621
  </button>
4622
  </div>
4623
  </div>
 
4821
  <span id="authToggleText">Don't have an account?</span>
4822
  <span class="auth-toggle" id="authToggleBtn" onclick="toggleAuthMode()">Sign Up</span>
4823
  </div>
4824
+ <div style="margin-top: 15px; text-align: center; font-size: 13px; opacity: 0.7;">
4825
+ <span style="color: var(--text-secondary);">Or </span>
4826
+ <span class="auth-toggle" onclick="loginAsGuest()" style="color: #10a37f; cursor: pointer; font-weight: 600;">Continue as Guest</span>
4827
+ </div>
4828
  </div>
4829
  </div>
4830
 
 
6067
  const thinkingDiv = showThinking();
6068
  const messageContent = thinkingDiv.querySelector('.message-content');
6069
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6070
  // Task 15: Stream the AI response normally (backend handles tool detection)
6071
  addMessage(query, 'user');
6072
 
 
6110
  if (!line.trim()) continue;
6111
  try {
6112
  const data = JSON.parse(line);
6113
+
6114
+ if (data.error) {
6115
+ hideThinking(thinkingDiv);
6116
+ addMessage(data.error, 'ai');
6117
+ return;
6118
+ }
6119
 
6120
  // Task: Handle search results from backend synthesis
6121
  if (data.search_results) {
 
6177
  const badge = (toolsUsed.includes('search')) ? '<div class="compiled-search-badge"><i data-lucide="brain"></i> Synthesized Research Report</div>' : '';
6178
  aiContentEl.innerHTML = badge + marked.parse(fullResponse);
6179
 
6180
+ // If backend used video tool, call video API and append to message
6181
+ if (toolsUsed.includes('video')) {
6182
+ const videoContainer = document.createElement('div');
6183
+ videoContainer.className = 'image-card';
6184
+ videoContainer.innerHTML = `<div class="img-skeleton visible" style="height: 300px; background: rgba(255,255,255,0.05); border-radius: 12px; animation: pulse 1.5s infinite; display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 10px;">
6185
+ <i data-lucide="video" class="animate-pulse" style="width:40px; height:40px; color: #10a37f;"></i>
6186
+ <span style="font-size: 14px; color: var(--text-secondary);">Generating AI Video...</span>
6187
+ </div>`;
6188
+ aiContentEl.appendChild(videoContainer);
6189
+ smoothScrollToBottom();
6190
+ if (window.lucide) lucide.createIcons();
6191
+
6192
+ try {
6193
+ const videoRes = await fetch('/api/video/generate', {
6194
+ method: 'POST',
6195
+ headers: {'Content-Type': 'application/json'},
6196
+ body: JSON.stringify({ prompt: query })
6197
+ });
6198
+ const videoData = await videoRes.json();
6199
+
6200
+ if (videoData.status === 'success') {
6201
+ const videoId = 'vid-' + Date.now();
6202
+ if (videoData.is_motion_image) {
6203
+ videoContainer.innerHTML = `
6204
+ <div class="video-container" style="background:none; position: relative;">
6205
+ <img src="${videoData.video_url}" alt="${query}" class="motion-image" style="width:100%; border-radius:12px; display:block;">
6206
+ <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0,0,0,0.5); border-radius: 50%; width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; pointer-events: none;">
6207
+ <i data-lucide="play" style="width: 30px; height: 30px; color: white; fill: white;"></i>
6208
+ </div>
6209
+ </div>
6210
+ <div class="image-card-actions">
6211
+ <a href="${videoData.video_url}" class="img-btn" onclick="downloadImage(event, '${videoData.video_url}')"><i data-lucide="download"></i> Download</a>
6212
+ <button class="img-btn" onclick="openVideoOverlayModal('${videoData.video_url}')"><i data-lucide="type"></i> Add Text</button>
6213
+ </div>
6214
+ `;
6215
+ } else {
6216
+ videoContainer.innerHTML = `
6217
+ <div class="video-container" id="${videoId}-container">
6218
+ <video id="${videoId}" autoplay loop muted playsinline>
6219
+ <source src="${videoData.video_url}" type="video/mp4">
6220
+ </video>
6221
+ <div class="custom-video-controls">
6222
+ <button class="vid-ctrl-btn play-pause"><i data-lucide="pause"></i></button>
6223
+ <div class="video-progress"><div class="video-progress-filled"></div></div>
6224
+ <div class="volume-container">
6225
+ <button class="vid-ctrl-btn volume-btn"><i data-lucide="volume-x"></i></button>
6226
+ <div class="volume-slider-vertical"><input type="range" min="0" max="1" step="0.1" value="0"></div>
6227
+ </div>
6228
+ </div>
6229
+ </div>
6230
+ <div class="image-card-actions">
6231
+ <a href="${videoData.video_url}" download class="img-btn"><i data-lucide="download"></i> Download Video</a>
6232
+ <button class="img-btn" onclick="openVideoOverlayModal('${videoData.video_url}')"><i data-lucide="type"></i> Add Text</button>
6233
+ </div>
6234
+ `;
6235
+ }
6236
+ if (window.lucide) lucide.createIcons();
6237
+ if (!videoData.is_motion_image) initCustomVideoPlayer(videoId);
6238
+ } else {
6239
+ videoContainer.innerHTML = `<div style="padding: 20px; color: #f87171;"><i data-lucide="alert-circle"></i> Video failed: ${videoData.error}</div>`;
6240
+ if (window.lucide) lucide.createIcons();
6241
+ }
6242
+ } catch (vErr) {
6243
+ videoContainer.innerHTML = `<div style="padding: 20px; color: #f87171;"><i data-lucide="alert-circle"></i> Video connection error.</div>`;
6244
+ if (window.lucide) lucide.createIcons();
6245
+ }
6246
+ smoothScrollToBottom();
6247
+ }
6248
+
6249
  // If backend used image tool, call image API and append to message
6250
  if (toolsUsed.includes('image')) {
6251
  const imageContainer = document.createElement('div');