Gush AI
`; const blob = new Blob(['\ufeff' + fullHtml], { type: 'application/msword' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = docTitle + '.doc'; a.click(); showToast('Word Document (.doc) exported successfully!', 'success'); } else if (format === 'pdf') { generatePdfDownload(cleanHtmlBody, docTitle); } } function generatePdfDownload(bodyHtml, title) { const wrapper = document.createElement('div'); wrapper.innerHTML = `

${escapeHtml(title)}

Generated ${escapeHtml(new Date().toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' }))}

${bodyHtml}
`; showToast('Generating PDF...', 'info'); html2pdf().set({ margin: [14, 12, 14, 12], filename: title.replace(/[^a-z0-9\-_]+/gi, '_') + '.pdf', html2canvas: { scale: 2, useCORS: true }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, pagebreak: { mode: ['css', 'legacy'] } }).from(wrapper).save() .then(() => showToast('PDF downloaded successfully!', 'success')) .catch(err => showToast('PDF export failed: ' + err.message, 'error')); } function openPluginPanel(slug, label) { const frame = document.getElementById('plugin-iframe'); const title = document.getElementById('plugin-panel-title'); if (frame) { if (slug.startsWith('/') || slug.startsWith('http') || slug.startsWith('..')) { frame.src = slug; } else { frame.src = '/' + slug + '/'; } } if (title) title.textContent = label || slug; setMode('plugin'); } function openGushConnectModal() { if (!isLoggedIn) { const gate = document.getElementById('auth-gate'); if (gate) gate.style.display = 'flex'; return; } const modal = document.getElementById('gush-connect-modal'); if (modal) modal.style.display = 'flex'; if (typeof loadUserIntegrations === 'function') loadUserIntegrations(); if (typeof loadBuiltinServicesList === 'function') loadBuiltinServicesList(); } async function loadBuiltinServicesList() { const wrap = document.getElementById('builtin-services-list'); if (!wrap) return; wrap.innerHTML = '
Loading available services…
'; try { const services = (typeof loadAvailableServices === 'function') ? await loadAvailableServices(true) : await fetch('?action=get_available_services').then(r => r.json()).then(r => (r && r.ok) ? r.services : []); if (!services || !services.length) { wrap.innerHTML = '
No services are available yet.
'; return; } wrap.innerHTML = services.map(function (s) { const priceLabel = (s.pricing && (s.pricing.free_limit > 0 || s.pricing.price_ngn > 0)) ? `${s.pricing.free_limit} free / ${s.pricing.free_window_hours}h, then ₦${Number(s.pricing.price_ngn).toFixed(2)}` : 'Free'; const visBadge = s.visibility === 'private' ? 'Private' : ''; return `
${esc(s.name || s.key)} ${esc(s.command || '')}${visBadge}
${esc(s.description || '')}
${esc(priceLabel)}
`; }).join(''); } catch (e) { wrap.innerHTML = '
Could not load services.
'; } } function closeGushConnectModal() { const modal = document.getElementById('gush-connect-modal'); if (modal) modal.style.display = 'none'; } function switchGushConnectSubTab(tabName) { const tabs = ['integrations', 'sdk', 'marketplace', 'community']; tabs.forEach(t => { const btn = document.getElementById('gc-tab-' + t); const pane = document.getElementById('gc-pane-' + t); if (btn) { if (t === tabName) { btn.classList.add('active', 'text-cyan-400'); btn.classList.remove('text-slate-400'); } else { btn.classList.remove('active', 'text-cyan-400'); btn.classList.add('text-slate-400'); } } if (pane) { pane.style.display = (t === tabName) ? 'block' : 'none'; } }); if (tabName === 'marketplace' && typeof loadMarketplaceList === 'function') loadMarketplaceList(); } document.addEventListener('DOMContentLoaded', function () { const sel = document.getElementById('search-pref'); const savedPref = localStorage.getItem('gush_search_pref'); if (sel && savedPref) { sel.value = savedPref; if (typeof liveSearchPref !== 'undefined') { liveSearchPref = savedPref; } window.liveSearchPref = savedPref; } if (typeof toggleDeepBadgeVisibility === 'function') toggleDeepBadgeVisibility(); if (typeof applyGroundingUI === 'function') applyGroundingUI(); });