umar8902 commited on
Commit
20907de
·
verified ·
1 Parent(s): 7809ff3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +99 -61
index.html CHANGED
@@ -4038,6 +4038,41 @@
4038
  display: none;
4039
  }
4040
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4041
  </style>
4042
  </head>
4043
 
@@ -4068,7 +4103,8 @@
4068
  <p class="hero-subtitle">Chat with Nexa AI to get answers, generate stunning images, and boost your productivity. Your personal AI assistant for work and creativity.</p>
4069
  <div class="cta-container">
4070
  <button onclick="enterApp()" class="btn-primary landing-cta">Start Chatting — Free Forever</button>
4071
- <button class="btn-secondary" data-section="featuresSection">View Demo</button>
 
4072
  </div>
4073
  <div class="trust-badges">
4074
  <div class="trust-badge"><i data-lucide="shield-check"></i> No credit card required</div>
@@ -4298,7 +4334,8 @@
4298
  <span>Deep Research</span>
4299
  </div>
4300
  <label class="switch">
4301
- <input type="checkbox" id="deepResearchToggle">
 
4302
  <span class="slider"></span>
4303
  </label>
4304
  </div>
@@ -4530,12 +4567,13 @@
4530
  <button class="action-btn mic-btn" id="micBtn" onclick="toggleSpeechRecognition()" title="Voice Input">
4531
  <i data-lucide="mic"></i>
4532
  </button>
4533
- <button class="send-button" id="sendBtn" onclick="sendMessage()">
 
4534
  <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4535
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18" />
4536
  </svg>
4537
  </button>
4538
- <button class="stop-button" id="stopBtn" onclick="stopAI()">
4539
  <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4540
  <rect x="6" y="6" width="12" height="12" rx="2" fill="currentColor" />
4541
  </svg>
@@ -4814,6 +4852,7 @@
4814
  };
4815
 
4816
  // Critical Global Functions (Must be defined first)
 
4817
  function enterApp() {
4818
  try {
4819
  const landing = document.getElementById('landingPage');
@@ -4822,11 +4861,13 @@
4822
 
4823
  if (!currentUser) {
4824
  if (landing) {
 
 
4825
  landing.classList.add('hidden');
4826
- setTimeout(() => { if (landing) landing.style.display = 'none'; }, 800);
4827
  }
4828
  if (authOvl) {
4829
  authOvl.style.display = 'flex';
 
4830
  authOvl.classList.add('show');
4831
  }
4832
  if (window.lightningTimeout) {
@@ -4854,6 +4895,7 @@
4854
  }
4855
  }
4856
 
 
4857
  function scrollToSection(id) {
4858
  try {
4859
  const el = document.getElementById(id);
@@ -5011,15 +5053,9 @@
5011
  if (modelDropdown) modelDropdown.classList.remove('open');
5012
  });
5013
 
 
5014
  function toggleDeepResearch(checked) {
5015
- const toggle = document.getElementById('deepResearchToggle');
5016
- if (checked !== undefined) {
5017
- isDeepResearch = checked;
5018
- } else {
5019
- isDeepResearch = !isDeepResearch;
5020
- toggle.checked = isDeepResearch;
5021
- }
5022
-
5023
  localStorage.setItem('nexa_ai_deep_research', isDeepResearch);
5024
 
5025
  // Update UI indicator
@@ -5028,8 +5064,6 @@
5028
  if (isDeepResearch) indicator.classList.add('visible');
5029
  else indicator.classList.remove('visible');
5030
  }
5031
-
5032
- console.log(`Deep Research Mode: ${isDeepResearch}`);
5033
  }
5034
 
5035
  function initAiModes() {
@@ -5461,21 +5495,31 @@
5461
  }
5462
 
5463
  function stopAI() {
5464
- if (abortController) {
5465
- abortController.abort();
 
 
 
 
 
 
5466
  abortController = null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5467
  }
5468
- isTyping = false;
5469
- isGeneratingImage = false;
5470
- isSearching = false;
5471
- isAnalyzingFile = false;
5472
-
5473
- // UI Cleanup
5474
- const thinking = document.getElementById('thinkingMessage');
5475
- if (thinking) thinking.remove();
5476
-
5477
- if (stopBtn) stopBtn.classList.remove('active');
5478
- if (sendBtn) sendBtn.style.display = 'flex';
5479
  }
5480
 
5481
  function handleImageRemix(encodedQuery) {
@@ -5519,7 +5563,7 @@
5519
  }
5520
 
5521
  function setupEventListeners() {
5522
- // SINGLE Global Delegation for EVERYTHING (Landing + App)
5523
  document.addEventListener('click', (e) => {
5524
  const target = e.target;
5525
 
@@ -5528,29 +5572,19 @@
5528
  // 1. Landing Navigation Links (Features, Pricing, etc.)
5529
  const navLink = target.closest('.nav-link[data-section]');
5530
  if (navLink) {
5531
- const sectionId = navLink.getAttribute('data-section');
5532
- scrollToSection(sectionId);
5533
  e.preventDefault();
 
5534
  return;
5535
  }
5536
 
5537
  // 2. Landing CTA Buttons ("Try Nexa AI", "Start Chatting")
5538
  if (target.closest('.landing-cta')) {
5539
- enterApp();
5540
- e.preventDefault();
5541
- return;
5542
- }
5543
-
5544
- // 3. Landing "View Demo" Button
5545
- const demoBtn = target.closest('.btn-secondary[data-section]');
5546
- if (demoBtn) {
5547
- const sectionId = demoBtn.getAttribute('data-section');
5548
- scrollToSection(sectionId);
5549
  e.preventDefault();
 
5550
  return;
5551
  }
5552
 
5553
- // 8. FAQ Items
5554
  const faqQuestion = target.closest('.faq-question');
5555
  if (faqQuestion) {
5556
  const item = faqQuestion.parentElement;
@@ -5574,23 +5608,12 @@
5574
  return;
5575
  }
5576
 
5577
- // 6. Tool Actions (+ Menu items)
5578
  const toolBtn = target.closest('.tool-btn');
5579
  if (toolBtn) {
5580
- // Try to find action from handleToolAction call or text
5581
- let action = toolBtn.getAttribute('onclick')?.match(/'(.*)'/)?.[1];
5582
- if (!action) {
5583
- const text = toolBtn.textContent.toLowerCase();
5584
- if (text.includes('image')) action = 'image';
5585
- else if (text.includes('search')) action = 'search';
5586
- else if (text.includes('video')) action = 'video';
5587
- else if (text.includes('upload')) action = 'upload';
5588
- else if (text.includes('voice')) action = 'voice';
5589
- }
5590
- if (action) {
5591
- e.preventDefault();
5592
- handleToolAction(action);
5593
- }
5594
  return;
5595
  }
5596
 
@@ -5605,14 +5628,15 @@
5605
  return;
5606
  }
5607
 
5608
- // 9. Account Dropdown Toggle
5609
  if (target.closest('.account-btn')) {
5610
  toggleAccountDropdown();
5611
  return;
5612
  }
5613
 
5614
- // 10. Close dropdowns when clicking outside
5615
  if (!target.closest('.mode-dropdown') && !target.closest('.account-btn') && !target.closest('.top-right-menu')) {
 
5616
  document.querySelectorAll('.mode-dropdown, .account-dropdown').forEach(d => d.classList.remove('open', 'show'));
5617
  }
5618
 
@@ -7061,6 +7085,8 @@
7061
  }
7062
 
7063
  function startNewChat() {
 
 
7064
  currentConversationId = null;
7065
  const messageInput = document.getElementById('messageInput');
7066
  if (messageInput) messageInput.placeholder = "Message Nexa AI...";
@@ -7427,8 +7453,12 @@
7427
  }
7428
 
7429
  // Account dropdown
 
7430
  function toggleAccountDropdown() {
7431
- if (accountDropdown) accountDropdown.classList.toggle('show');
 
 
 
7432
  }
7433
 
7434
  // Hidden file input
@@ -7733,10 +7763,13 @@
7733
  if (e.target === document.getElementById('imgModalOverlay')) closeImageGenModal();
7734
  }
7735
 
 
7736
  async function generateImage() {
 
7737
  const prompt = document.getElementById('imgPromptInput').value.trim();
7738
  if (!prompt) return;
7739
 
 
7740
  const genBtn = document.getElementById('imgGenerateBtn');
7741
  const skeleton = document.getElementById('imgSkeleton');
7742
  const resultArea = document.getElementById('imgResultArea');
@@ -7764,6 +7797,7 @@
7764
  resultArea.classList.add('visible');
7765
  statusEl.textContent = '✓ Done!';
7766
  genBtn.disabled = false;
 
7767
  };
7768
  img.onerror = () => {
7769
  throw new Error("Failed to load image from Pollinations AI");
@@ -7774,6 +7808,7 @@
7774
  skeleton.classList.remove('visible');
7775
  statusEl.textContent = '✗ Error: ' + err.message;
7776
  genBtn.disabled = false;
 
7777
  }
7778
  }
7779
 
@@ -7903,7 +7938,10 @@
7903
  }
7904
 
7905
  function handleSettingsOverlayClick(e) {
7906
- if (e.target === document.getElementById('settingsModalOverlay')) closeSettings();
 
 
 
7907
  }
7908
 
7909
  let isAutoVoiceEnabled = localStorage.getItem('nexa_auto_voice') !== 'false';
 
4038
  display: none;
4039
  }
4040
  }
4041
+ /* FIXED: Added visual states for disabled buttons */
4042
+ .send-button:disabled {
4043
+ opacity: 0.3 !important;
4044
+ cursor: not-allowed !important;
4045
+ transform: none !important;
4046
+ }
4047
+
4048
+ .btn-primary:disabled {
4049
+ opacity: 0.6 !important;
4050
+ cursor: wait !important;
4051
+ }
4052
+
4053
+ /* FIXED: Ensure auth overlay is always on top */
4054
+ #authOverlay {
4055
+ z-index: 9999 !important;
4056
+ }
4057
+
4058
+ /* FIXED: Send/Stop button positioning */
4059
+ .input-actions {
4060
+ position: relative;
4061
+ display: flex;
4062
+ align-items: center;
4063
+ gap: 8px;
4064
+ }
4065
+
4066
+ .stop-button {
4067
+ display: none;
4068
+ background: var(--bg-secondary);
4069
+ border: 1px solid var(--border-color);
4070
+ color: var(--text-primary);
4071
+ }
4072
+
4073
+ .stop-button.active {
4074
+ display: flex;
4075
+ }
4076
  </style>
4077
  </head>
4078
 
 
4103
  <p class="hero-subtitle">Chat with Nexa AI to get answers, generate stunning images, and boost your productivity. Your personal AI assistant for work and creativity.</p>
4104
  <div class="cta-container">
4105
  <button onclick="enterApp()" class="btn-primary landing-cta">Start Chatting — Free Forever</button>
4106
+ <!-- FIXED: Replaced data-section with direct onclick for reliability -->
4107
+ <button class="btn-secondary" onclick="scrollToSection('featuresSection')">View Demo</button>
4108
  </div>
4109
  <div class="trust-badges">
4110
  <div class="trust-badge"><i data-lucide="shield-check"></i> No credit card required</div>
 
4334
  <span>Deep Research</span>
4335
  </div>
4336
  <label class="switch">
4337
+ <!-- FIXED: Added explicit parameter to toggleDeepResearch -->
4338
+ <input type="checkbox" id="deepResearchToggle" onchange="toggleDeepResearch(this.checked)">
4339
  <span class="slider"></span>
4340
  </label>
4341
  </div>
 
4567
  <button class="action-btn mic-btn" id="micBtn" onclick="toggleSpeechRecognition()" title="Voice Input">
4568
  <i data-lucide="mic"></i>
4569
  </button>
4570
+ <!-- FIXED: Removed inline onclick to prevent double-firing and used consistent SVG icons -->
4571
+ <button class="send-button" id="sendBtn" title="Send message (Enter)">
4572
  <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4573
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 10l7-7m0 0l7 7m-7-7v18" />
4574
  </svg>
4575
  </button>
4576
+ <button class="stop-button" id="stopBtn" title="Stop generating (Esc)">
4577
  <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
4578
  <rect x="6" y="6" width="12" height="12" rx="2" fill="currentColor" />
4579
  </svg>
 
4852
  };
4853
 
4854
  // Critical Global Functions (Must be defined first)
4855
+ <!-- FIXED: Optimized enterApp to handle unauthenticated state properly -->
4856
  function enterApp() {
4857
  try {
4858
  const landing = document.getElementById('landingPage');
 
4861
 
4862
  if (!currentUser) {
4863
  if (landing) {
4864
+ // Immediately hide landing page
4865
+ landing.style.display = 'none';
4866
  landing.classList.add('hidden');
 
4867
  }
4868
  if (authOvl) {
4869
  authOvl.style.display = 'flex';
4870
+ authOvl.style.zIndex = '9999'; // Ensure auth is above everything
4871
  authOvl.classList.add('show');
4872
  }
4873
  if (window.lightningTimeout) {
 
4895
  }
4896
  }
4897
 
4898
+ <!-- FIXED: Improved scrollToSection with null-safety and smooth scrolling -->
4899
  function scrollToSection(id) {
4900
  try {
4901
  const el = document.getElementById(id);
 
5053
  if (modelDropdown) modelDropdown.classList.remove('open');
5054
  });
5055
 
5056
+ <!-- FIXED: Removed inversion logic and added explicit parameter -->
5057
  function toggleDeepResearch(checked) {
5058
+ isDeepResearch = !!checked;
 
 
 
 
 
 
 
5059
  localStorage.setItem('nexa_ai_deep_research', isDeepResearch);
5060
 
5061
  // Update UI indicator
 
5064
  if (isDeepResearch) indicator.classList.add('visible');
5065
  else indicator.classList.remove('visible');
5066
  }
 
 
5067
  }
5068
 
5069
  function initAiModes() {
 
5495
  }
5496
 
5497
  function stopAI() {
5498
+ try {
5499
+ if (abortController) {
5500
+ abortController.abort();
5501
+ }
5502
+ } catch (e) {
5503
+ console.error("Stop AI error:", e);
5504
+ } finally {
5505
+ // FIXED: Ensure all states are reset in finally block
5506
  abortController = null;
5507
+ isTyping = false;
5508
+ isGeneratingImage = false;
5509
+ isSearching = false;
5510
+ isAnalyzingFile = false;
5511
+
5512
+ // UI Cleanup
5513
+ const thinking = document.getElementById('thinkingMessage');
5514
+ if (thinking) thinking.remove();
5515
+
5516
+ if (stopBtn) stopBtn.classList.remove('active');
5517
+ if (sendBtn) {
5518
+ sendBtn.style.display = 'flex';
5519
+ sendBtn.disabled = false;
5520
+ }
5521
+ updateSendButtonState();
5522
  }
 
 
 
 
 
 
 
 
 
 
 
5523
  }
5524
 
5525
  function handleImageRemix(encodedQuery) {
 
5563
  }
5564
 
5565
  function setupEventListeners() {
5566
+ // FIXED: Restructured with early returns to prevent fall-through bugs
5567
  document.addEventListener('click', (e) => {
5568
  const target = e.target;
5569
 
 
5572
  // 1. Landing Navigation Links (Features, Pricing, etc.)
5573
  const navLink = target.closest('.nav-link[data-section]');
5574
  if (navLink) {
 
 
5575
  e.preventDefault();
5576
+ scrollToSection(navLink.getAttribute('data-section'));
5577
  return;
5578
  }
5579
 
5580
  // 2. Landing CTA Buttons ("Try Nexa AI", "Start Chatting")
5581
  if (target.closest('.landing-cta')) {
 
 
 
 
 
 
 
 
 
 
5582
  e.preventDefault();
5583
+ enterApp();
5584
  return;
5585
  }
5586
 
5587
+ // 3. FAQ Items
5588
  const faqQuestion = target.closest('.faq-question');
5589
  if (faqQuestion) {
5590
  const item = faqQuestion.parentElement;
 
5608
  return;
5609
  }
5610
 
5611
+ // 6. Tool Actions (Using data-action instead of regex parsing)
5612
  const toolBtn = target.closest('.tool-btn');
5613
  if (toolBtn) {
5614
+ e.preventDefault();
5615
+ const action = toolBtn.dataset.action;
5616
+ if (action) handleToolAction(action);
 
 
 
 
 
 
 
 
 
 
 
5617
  return;
5618
  }
5619
 
 
5628
  return;
5629
  }
5630
 
5631
+ // 8. Account Dropdown Toggle
5632
  if (target.closest('.account-btn')) {
5633
  toggleAccountDropdown();
5634
  return;
5635
  }
5636
 
5637
+ // 9. Close dropdowns when clicking outside
5638
  if (!target.closest('.mode-dropdown') && !target.closest('.account-btn') && !target.closest('.top-right-menu')) {
5639
+ isDropdownOpen = false;
5640
  document.querySelectorAll('.mode-dropdown, .account-dropdown').forEach(d => d.classList.remove('open', 'show'));
5641
  }
5642
 
 
7085
  }
7086
 
7087
  function startNewChat() {
7088
+ // FIXED: Close sidebar on mobile when starting a new chat
7089
+ closeSidebarOnMobile();
7090
  currentConversationId = null;
7091
  const messageInput = document.getElementById('messageInput');
7092
  if (messageInput) messageInput.placeholder = "Message Nexa AI...";
 
7453
  }
7454
 
7455
  // Account dropdown
7456
+ let isDropdownOpen = false; // FIXED: Track dropdown state globally
7457
  function toggleAccountDropdown() {
7458
+ if (accountDropdown) {
7459
+ isDropdownOpen = !isDropdownOpen;
7460
+ accountDropdown.classList.toggle('show', isDropdownOpen);
7461
+ }
7462
  }
7463
 
7464
  // Hidden file input
 
7763
  if (e.target === document.getElementById('imgModalOverlay')) closeImageGenModal();
7764
  }
7765
 
7766
+ let isGeneratingImageModal = false; // FIXED: Prevent double-clicks in modal
7767
  async function generateImage() {
7768
+ if (isGeneratingImageModal) return;
7769
  const prompt = document.getElementById('imgPromptInput').value.trim();
7770
  if (!prompt) return;
7771
 
7772
+ isGeneratingImageModal = true;
7773
  const genBtn = document.getElementById('imgGenerateBtn');
7774
  const skeleton = document.getElementById('imgSkeleton');
7775
  const resultArea = document.getElementById('imgResultArea');
 
7797
  resultArea.classList.add('visible');
7798
  statusEl.textContent = '✓ Done!';
7799
  genBtn.disabled = false;
7800
+ isGeneratingImageModal = false;
7801
  };
7802
  img.onerror = () => {
7803
  throw new Error("Failed to load image from Pollinations AI");
 
7808
  skeleton.classList.remove('visible');
7809
  statusEl.textContent = '✗ Error: ' + err.message;
7810
  genBtn.disabled = false;
7811
+ isGeneratingImageModal = false;
7812
  }
7813
  }
7814
 
 
7938
  }
7939
 
7940
  function handleSettingsOverlayClick(e) {
7941
+ // FIXED: Improved click-outside detection for settings modal
7942
+ if (e.target.closest('.settings-modal') === null) {
7943
+ closeSettings();
7944
+ }
7945
  }
7946
 
7947
  let isAutoVoiceEnabled = localStorage.getItem('nexa_auto_voice') !== 'false';