// modals.js — All modal dialogs
import { send, on } from './ws.js';
import { escHtml } from './ui.js';
import { isAuthenticated, loginWithEmail, signUpWithEmail, loginWithOAuth, logout, currentUser, userProfile, userSettings } from './auth.js';
let overlay, box;
function getOverlay() { return overlay || (overlay = document.getElementById('modal-overlay')); }
function getBox() { return box || (box = document.getElementById('modal-box')); }
export function openModal(html, opts = {}) {
const o = getOverlay(), b = getBox();
b.className = 'modal-box' + (opts.wide ? ' wide' : '');
b.innerHTML = html;
o.classList.remove('hidden');
if (opts.onOpen) opts.onOpen(b);
// Close on overlay click
o.onclick = (e) => { if (e.target === o) closeModal(); };
// Close on Escape
document.addEventListener('keydown', escHandler);
}
const escHandler = (e) => { if (e.key === 'Escape') closeModal(); };
export function closeModal() {
getOverlay().classList.add('hidden');
getBox().innerHTML = '';
document.removeEventListener('keydown', escHandler);
}
// ── Auth modal ────────────────────────────────────────────────────────────
export function openAuthModal(initialTab = 'signin') {
openModal(`
⚠️
You are about to share this whole session. Anyone with the link can import it into their account.
Generating link…
`, {
onOpen(b) {
b.querySelector('#share-generate-btn').addEventListener('click', () => {
b.querySelector('#share-loading').style.display = '';
b.querySelector('#share-generate-btn').disabled = true;
send({ type: 'sessions:share', sessionId });
on('sessions:shareUrl', function handler(msg) {
if (msg.sessionId !== sessionId) return;
import('./ws.js').then(({ off }) => off('sessions:shareUrl', handler));
b.querySelector('#share-loading').style.display = 'none';
b.querySelector('#share-url-wrap').style.display = '';
const input = b.querySelector('#share-url-input');
input.value = msg.url;
b.querySelector('#share-copy-btn').addEventListener('click', async () => {
await navigator.clipboard.writeText(msg.url).catch(() => {});
b.querySelector('#share-copy-btn').textContent = 'Copied!';
});
});
});
}
});
}
// ── Tool call modal ───────────────────────────────────────────────────────
export function showToolCallModal(call) {
const names = {
ollama_search: 'Web Search', read_web_page: 'Read Web Page',
generate_image: 'Image Generation', generate_video: 'Video Generation', generate_audio: 'Audio Generation',
};
const displayName = names[call.name] || call.name;
let argsDisplay = call.args || call.arguments || '{}';
if (typeof argsDisplay !== 'string') argsDisplay = JSON.stringify(argsDisplay, null, 2);
let resultDisplay = call.result || '—';
if (typeof resultDisplay !== 'string') resultDisplay = JSON.stringify(resultDisplay, null, 2);
openModal(`
`);
}
// ── Image modal ───────────────────────────────────────────────────────────
export function openImageModal(src) {
openModal(`
💬
Daily limit reached
Sign in or create a free account to keep chatting.
Guest usage resets every 24 hours.
`, {
onOpen(b) {
b.querySelector('#limit-signin').addEventListener('click', () => { closeModal(); openAuthModal('signin'); });
b.querySelector('#limit-signup').addEventListener('click', () => { closeModal(); openAuthModal('signup'); });
}
});
}
// ── Device session detail modal ───────────────────────────────────────────
export function openDeviceSessionModal(session, isCurrentSession) {
openModal(`
${isCurrentSession ? '
This is your current session.
' : ''}
`, {
onOpen(b) {
if (!isCurrentSession) {
b.querySelector('#revoke-session-btn')?.addEventListener('click', () => {
send({ type: 'account:revokeSession', token: session.token });
closeModal();
});
}
}
});
}
// ── Pasted content editor ─────────────────────────────────────────────────
export function openPasteEditor(content, onSave) {
openModal(`