(fileName, folder, sourceId = '')
| 495 | |
| 496 | // Full-screen OO open with hidden warm-up EVERY click, then real editor |
| 497 | async function openOnlyOffice(fileName, folder, sourceId = ''){ |
| 498 | let editor = null; |
| 499 | let removeThemeListener = () => {}; |
| 500 | let cfg = null; |
| 501 | let userClosed = false; |
| 502 | |
| 503 | // Build our full-screen modal |
| 504 | const modal = ensureOoFullscreenModal(); |
| 505 | const titleEl = modal.querySelector('.editor-title'); |
| 506 | if (titleEl) titleEl.innerHTML = `${t("editing")}: ${escapeHTML(fileName)}`; |
| 507 | |
| 508 | const destroy = (removeModal = true) => { |
| 509 | try { editor?.destroyEditor?.(); } catch (e) {} |
| 510 | try { removeThemeListener(); } catch (e) {} |
| 511 | if (removeModal) { try { modal.remove(); } catch (e) {} } |
| 512 | lockPageScroll(false); |
| 513 | }; |
| 514 | const onClose = () => { userClosed = true; destroy(true); }; |
| 515 | |
| 516 | modal.querySelector('#closeEditorX')?.addEventListener('click', onClose); |
| 517 | modal.addEventListener('keydown', (e) => { if (e.key === 'Escape') onClose(); }); |
| 518 | |
| 519 | try{ |
| 520 | // 1) Fetch config |
| 521 | const f = (!folder || folder === '') ? 'root' : String(folder); |
| 522 | const sid = normalizeSourceId(sourceId); |
| 523 | const params = new URLSearchParams({ |
| 524 | folder: f, |
| 525 | file: fileName |
| 526 | }); |
| 527 | if (sid) params.set('sourceId', sid); |
| 528 | const url = withBase(`/api/onlyoffice/config.php?${params.toString()}`); |
| 529 | const resp = await fetch(url, { credentials: 'include' }); |
| 530 | const text = await resp.text(); |
| 531 | |
| 532 | try { cfg = JSON.parse(text); } catch (e) { |
| 533 | throw new Error(`ONLYOFFICE config parse failed (HTTP ${resp.status}). First 120 chars: ${text.slice(0,120)}`); |
| 534 | } |
| 535 | if (!resp.ok) throw new Error(cfg?.error || `ONLYOFFICE config HTTP ${resp.status}`); |
| 536 | |
| 537 | // 2) Preconnect + load DocsAPI |
| 538 | injectOOPreconnect(cfg.documentServerOrigin || null); |
| 539 | await ensureOnlyOfficeApi(cfg.docs_api_js, cfg.documentServerOrigin); |
| 540 | |
| 541 | // 3) Theme + base events |
| 542 | const isDark = document.documentElement.classList.contains('dark-mode') |
| 543 | || /^(1|true)$/i.test(localStorage.getItem('darkMode') || ''); |
| 544 | cfg.events = (cfg.events && typeof cfg.events === 'object') ? cfg.events : {}; |
| 545 | cfg.editorConfig = cfg.editorConfig || {}; |
| 546 | cfg.editorConfig.customization = Object.assign( |
| 547 | {}, cfg.editorConfig.customization, { uiTheme: isDark ? 'theme-dark' : 'theme-light' } |
| 548 | ); |
| 549 | |
| 550 | // Preserve any events coming from PHP side |
| 551 | const prevOnRequestClose = cfg.events.onRequestClose; |
| 552 | const prevOnAppReady = cfg.events.onAppReady; |
| 553 | const prevOnDocumentReady = cfg.events.onDocumentReady; |
| 554 |
no test coverage detected