diff --git a/lib/document.ts b/lib/document.ts index 84e620f..8c4e581 100644 --- a/lib/document.ts +++ b/lib/document.ts @@ -30,12 +30,9 @@ export const onCreateNew = async (ext: string): Promise => { // Note: Loading is now shown in the menu button click handler // This function should not show loading again to avoid double loading indicators try { - // Hide control panel if it's visible + // Always hide control panel and ensure FAB is visible when creating new document if (hideControlPanelFn) { - const container = document.querySelector('#control-panel-container') as HTMLElement; - if (container && container.style.display !== 'none') { - hideControlPanelFn(); - } + hideControlPanelFn(); } setDocmentObj({ fileName: 'New_Document' + ext, @@ -62,88 +59,61 @@ export const onCreateNew = async (ext: string): Promise => { } }; -export const onOpenDocument = async (): Promise => { - return new Promise((resolve) => { - let resolved = false; - let cancelTimeout: NodeJS.Timeout | null = null; +export const onOpenDocument = (): void => { + // Clear previous event handler and value + fileInput.onchange = null; + fileInput.value = ''; - // Clear previous event handler and value - fileInput.onchange = null; - fileInput.value = ''; - - // Set up a longer timeout to detect if user cancelled (no change event) - // This handles the case where user cancels without triggering onchange - // Use a longer timeout (5 seconds) to avoid false positives - cancelTimeout = setTimeout(() => { - if (!resolved) { - resolved = true; - fileInput.value = ''; - fileInput.onchange = null; - resolve(false); - } - }, 5000); - - // Define the change handler - const handleChange = async (event: Event) => { - if (cancelTimeout) { - clearTimeout(cancelTimeout); - cancelTimeout = null; - } + // Define the change handler + const handleChange = async (event: Event) => { + const file = (event.target as HTMLInputElement).files?.[0]; - const file = (event.target as HTMLInputElement).files?.[0]; - - // Clear the handler to prevent multiple triggers - fileInput.onchange = null; + // Clear the handler to prevent multiple triggers + fileInput.onchange = null; - if (file && !resolved) { - resolved = true; - const { removeLoading } = showLoading(); - try { - if (hideControlPanelFn) { - hideControlPanelFn(); - } - setDocmentObj({ - fileName: file.name, - file: file, - url: await createObjectURL(file), - }); - await initX2T(); - const { fileName, file: fileBlob } = getDocmentObj(); - await handleDocumentOperation({ file: fileBlob, fileName, isNew: !fileBlob }); - // Clear file selection so the same file can be selected again - fileInput.value = ''; - // Show menu guide after document is loaded - if (showMenuGuideFn) { - setTimeout(() => { - showMenuGuideFn!(); - }, 1000); - } - resolve(true); - } catch (error) { - console.error('Error opening document:', error); - // Ensure control panel is shown on error - if (showControlPanelFn) { - showControlPanelFn(); - } - resolve(false); - } finally { - // Always remove loading, even if there's an error - removeLoading(); + // Only process if a file was actually selected + // If user cancelled, onchange won't fire, nothing happens + if (file) { + const { removeLoading } = showLoading(); + try { + if (hideControlPanelFn) { + hideControlPanelFn(); } - } else if (!resolved) { - // onchange fired but no file selected (user cancelled or cleared selection) - resolved = true; + setDocmentObj({ + fileName: file.name, + file: file, + url: await createObjectURL(file), + }); + await initX2T(); + const { fileName, file: fileBlob } = getDocmentObj(); + await handleDocumentOperation({ file: fileBlob, fileName, isNew: !fileBlob }); + // Clear file selection so the same file can be selected again fileInput.value = ''; - resolve(false); + // Show menu guide after document is loaded + if (showMenuGuideFn) { + setTimeout(() => { + showMenuGuideFn!(); + }, 1000); + } + } catch (error) { + console.error('Error opening document:', error); + // Ensure control panel is shown on error + if (showControlPanelFn) { + showControlPanelFn(); + } + } finally { + // Always remove loading, even if there's an error + removeLoading(); } - }; + } + // If no file selected, nothing happens (user cancelled) + }; - // Set the change handler - fileInput.onchange = handleChange; + // Set the change handler + fileInput.onchange = handleChange; - // Trigger file picker click event - fileInput.click(); - }); + // Trigger file picker click event + fileInput.click(); }; export const openDocumentFromUrl = async (url: string, fileName?: string): Promise => { diff --git a/lib/ui.ts b/lib/ui.ts index fe92c79..21bac3e 100644 --- a/lib/ui.ts +++ b/lib/ui.ts @@ -6,6 +6,13 @@ import { onCreateNew, onOpenDocument } from './document'; // Hide control panel and show top floating bar export const hideControlPanel = (): void => { const container = document.querySelector('#control-panel-container') as HTMLElement; + const fabContainer = document.querySelector('#fab-container') as HTMLElement; + + // Always ensure FAB is visible when hiding control panel + if (fabContainer) { + fabContainer.style.display = 'block'; + } + if (container) { // Immediately disable pointer events to prevent blocking container.style.pointerEvents = 'none'; @@ -13,7 +20,6 @@ export const hideControlPanel = (): void => { // Hide after transition for smooth animation setTimeout(() => { container.style.display = 'none'; - showTopFloatingBar(); }, 300); } }; @@ -28,19 +34,13 @@ export const showControlPanel = (): void => { container.style.opacity = '1'; }, 10); } - if (fabContainer) { + // Only hide FAB if editor is not open + // If editor is already open, keep FAB visible so user can access menu + if (fabContainer && !window.editor) { fabContainer.style.display = 'none'; } }; -// Show fixed action button -const showTopFloatingBar = (): void => { - const fabContainer = document.querySelector('#fab-container') as HTMLElement; - if (fabContainer) { - fabContainer.style.display = 'block'; - } -}; - // Create fixed action button in bottom right corner export const createFixedActionButton = (): HTMLElement => { const fabContainer = document.createElement('div'); @@ -58,7 +58,7 @@ export const createFixedActionButton = (): HTMLElement => { menuPanel.id = 'fab-menu'; menuPanel.className = 'fab-menu'; - const createMenuButton = (text: string, onClick: () => void | Promise) => { + const createMenuButton = (text: string, onClick: () => void | Promise, showLoadingImmediately = true) => { // Create wrapper for the entire menu item const menuItem = document.createElement('div'); menuItem.className = 'fab-menu-item'; @@ -77,8 +77,12 @@ export const createFixedActionButton = (): HTMLElement => { button.addEventListener('click', async () => { hideMenu(); - // Show loading immediately before any async operations - const { removeLoading } = showLoading(); + // Only show loading immediately if specified (for operations that don't require user interaction) + let removeLoading: (() => void) | null = null; + if (showLoadingImmediately) { + const loadingResult = showLoading(); + removeLoading = loadingResult.removeLoading; + } try { // Small delay to ensure menu hide animation completes await new Promise((resolve) => setTimeout(resolve, 100)); @@ -88,8 +92,10 @@ export const createFixedActionButton = (): HTMLElement => { // Show control panel on error showControlPanel(); } finally { - // Always remove loading - removeLoading(); + // Only remove loading if it was shown + if (removeLoading) { + removeLoading(); + } } }); @@ -98,14 +104,15 @@ export const createFixedActionButton = (): HTMLElement => { }; menuPanel.appendChild( - createMenuButton(t('uploadDocument'), async () => { - const result = await onOpenDocument(); - // If user cancelled file selection, show control panel again - // (FAB menu will be hidden by hideMenu() call in createMenuButton) - if (!result) { - showControlPanel(); - } - }), + createMenuButton( + t('uploadDocument'), + () => { + onOpenDocument(); + // If user cancelled, nothing happens (onchange won't fire) + // If user selected file, document will be opened in handleChange + }, + false, // Don't show loading immediately - wait for file selection + ), ); menuPanel.appendChild( createMenuButton(t('newWord'), async () => { @@ -310,13 +317,10 @@ export const createControlPanel = (): void => { }; // Create four buttons - const uploadButton = createTextButton('upload-button', t('uploadDocument'), async () => { - const result = await onOpenDocument(); - // Only hide control panel if file was successfully selected - // If user cancelled, control panel remains visible - if (result) { - hideControlPanel(); - } + const uploadButton = createTextButton('upload-button', t('uploadDocument'), () => { + onOpenDocument(); + // If user cancelled, nothing happens (onchange won't fire, control panel remains visible) + // If user selected file, document will be opened and control panel will be hidden in handleChange }); buttonGroup.appendChild(uploadButton); diff --git a/public/sdkjs/cell/sdk-all-min.js b/public/sdkjs/cell/sdk-all-min.js index d59d370..1f5cba7 100644 --- a/public/sdkjs/cell/sdk-all-min.js +++ b/public/sdkjs/cell/sdk-all-min.js @@ -20659,9 +20659,7 @@ function mg(t, e) { (t.AscCommon.sHh = function (e, s) { t.NATIVE_EDITOR_ENJINE || d( - ('chrome-extension:' == t.location?.protocol - ? 'https://bangong.360.cn/office/SmartArts/' - : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', + (false ? '' : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', function (t) { if (t && t.response) { ((t = AscCommon.a$d(t)), diff --git a/public/sdkjs/cell/sdk-all.js b/public/sdkjs/cell/sdk-all.js index 685c53c..2b5236f 100644 --- a/public/sdkjs/cell/sdk-all.js +++ b/public/sdkjs/cell/sdk-all.js @@ -128328,8 +128328,8 @@ var t = new XMLHttpRequest(); t.sRa = this; let w; - const z = n.includes('bangong.360.cn'); - 'chrome-extension:' != a.location?.protocol || z ? ((n += r[this.jb]), (w = !0)) : (n = this.jb); + const z = false; + z ? ((n += r[this.jb]), (w = !0)) : (n = this.jb); t.open('GET', n, !0); 'undefined' === typeof ArrayBuffer || a.opera || (t.responseType = 'arraybuffer'); t.overrideMimeType @@ -128350,12 +128350,11 @@ this.sRa.externalCallback && this.sRa.externalCallback(); }; t.onerror = function () { - z - ? (this.sRa.GFe++, - 3 > this.sRa.GFe - ? (this.sRa.vE = 0) - : ((this.sRa.vE = 2), a.Asc.editor.Pe('asc_onError', Asc.Qe.Yb.HFe, Asc.Qe.ee.y4))) - : this.sRa.yFe('https://bangong.360.cn/office/fonts/'); + // Use local error handling only + this.sRa.GFe++; + 3 > this.sRa.GFe + ? (this.sRa.vE = 0) + : ((this.sRa.vE = 2), a.Asc.editor.Pe('asc_onError', Asc.Qe.Yb.HFe, Asc.Qe.ee.y4)); }; t.send(null); }; @@ -128541,13 +128540,8 @@ })(window, window.document); (function (a) { function b() { - 'chrome-extension:' == a.location?.protocol - ? ((this.xZc = '../../../../fonts/'), - fetch('file:///C:').catch(() => { - AscFonts.Opi = !1; - this.xZc = 'https://bangong.360.cn/office/fonts/'; - })) - : (this.xZc = '../../../../fonts/'); + // Always use local fonts path + this.xZc = '../../../../fonts/'; this.EZb = AscFonts.odf; this.fPd = AscFonts.MZb; this.Uvc = AscFonts.OZb; @@ -407691,11 +407685,7 @@ Rch: function (p, k) { let r = a.origin; b === r && (r = a.location.origin); - return k.origin === r || (k.origin && 0 === k.origin.indexOf('chrome-extension://')) - ? !0 - : (p = this.FRa(p)) && 0 === p.DT.indexOf(k.origin) - ? !0 - : !1; + return k.origin === r ? !0 : (p = this.FRa(p)) && 0 === p.DT.indexOf(k.origin) ? !0 : !1; }, Kzc: function (p) { if (0 !== this.sTa.length) { diff --git a/public/sdkjs/slide/sdk-all-min.js b/public/sdkjs/slide/sdk-all-min.js index e26ea6f..b62bc48 100644 --- a/public/sdkjs/slide/sdk-all-min.js +++ b/public/sdkjs/slide/sdk-all-min.js @@ -20368,9 +20368,7 @@ function Ff(t, e) { (t.AscCommon.C_g = function (e, o) { t.NATIVE_EDITOR_ENJINE || p( - ('chrome-extension:' == t.location?.protocol - ? 'https://bangong.360.cn/office/SmartArts/' - : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', + (false ? '' : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', function (t) { if (t && t.response) { ((t = AscCommon.bXe(t)), diff --git a/public/sdkjs/slide/sdk-all.js b/public/sdkjs/slide/sdk-all.js index 15b05f3..75e59bc 100644 --- a/public/sdkjs/slide/sdk-all.js +++ b/public/sdkjs/slide/sdk-all.js @@ -129449,8 +129449,8 @@ var t = new XMLHttpRequest(); t.wFa = this; let w; - const z = r.includes('bangong.360.cn'); - 'chrome-extension:' != a.location?.protocol || z ? ((r += p[this.Ya]), (w = !0)) : (r = this.Ya); + const z = false; + z ? ((r += p[this.Ya]), (w = !0)) : (r = this.Ya); t.open('GET', r, !0); 'undefined' === typeof ArrayBuffer || a.opera || (t.responseType = 'arraybuffer'); t.overrideMimeType @@ -129471,12 +129471,11 @@ this.wFa.externalCallback && this.wFa.externalCallback(); }; t.onerror = function () { - z - ? (this.wFa.hge++, - 3 > this.wFa.hge - ? (this.wFa.lA = 0) - : ((this.wFa.lA = 2), a.Asc.editor.Jc('asc_onError', Asc.Kf.gf.ige, Asc.Kf.yo.E6))) - : this.wFa.age('https://bangong.360.cn/office/fonts/'); + // Use local error handling only + this.wFa.hge++; + 3 > this.wFa.hge + ? (this.wFa.lA = 0) + : ((this.wFa.lA = 2), a.Asc.editor.Jc('asc_onError', Asc.Kf.gf.ige, Asc.Kf.yo.E6)); }; t.send(null); }; @@ -129662,13 +129661,8 @@ })(window, window.document); (function (a) { function b() { - 'chrome-extension:' == a.location?.protocol - ? ((this.zBc = '../../../../fonts/'), - fetch('file:///C:').catch(() => { - AscFonts.BQh = !1; - this.zBc = 'https://bangong.360.cn/office/fonts/'; - })) - : (this.zBc = '../../../../fonts/'); + // Always use local fonts path + this.zBc = '../../../../fonts/'; this.xHb = AscFonts.YKe; this.rnd = AscFonts.HHb; this.xOd = AscFonts.Jnb; @@ -353499,11 +353493,7 @@ Yzg: function (n, k) { let p = a.origin; b === p && (p = a.location.origin); - return k.origin === p || (k.origin && 0 === k.origin.indexOf('chrome-extension://')) - ? !0 - : (n = this.HFa(n)) && 0 === n.PN.indexOf(k.origin) - ? !0 - : !1; + return k.origin === p ? !0 : (n = this.HFa(n)) && 0 === n.PN.indexOf(k.origin) ? !0 : !1; }, Gec: function (n) { if (0 !== this.oHa.length) { diff --git a/public/sdkjs/word/sdk-all-min.js b/public/sdkjs/word/sdk-all-min.js index 574bc43..23adec4 100644 --- a/public/sdkjs/word/sdk-all-min.js +++ b/public/sdkjs/word/sdk-all-min.js @@ -27025,9 +27025,7 @@ bc.Asc.c_oAscDateTimeFormat = bc.Asc.ZYb = xf; t.AscCommon.$Kg = function (e, o) { if (!t.NATIVE_EDITOR_ENJINE) { d( - (t.location?.protocol == 'chrome-extension:' - ? 'https://bangong.360.cn/office/SmartArts/' - : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', + (false ? '' : '../../../../sdkjs/common/SmartArts/') + 'SmartArts.bin', function (t) { if (t && t.response) { t = AscCommon.mDc(t); diff --git a/public/sdkjs/word/sdk-all.js b/public/sdkjs/word/sdk-all.js index 1fdaa4d..3b2e8e8 100644 --- a/public/sdkjs/word/sdk-all.js +++ b/public/sdkjs/word/sdk-all.js @@ -127212,8 +127212,8 @@ var t = new XMLHttpRequest(); t.QCa = this; let x; - const y = r.includes('bangong.360.cn'); - 'chrome-extension:' != a.location?.protocol || y ? ((r += p[this.Za]), (x = !0)) : (r = this.Za); + const y = false; + y ? ((r += p[this.Za]), (x = !0)) : (r = this.Za); t.open('GET', r, !0); 'undefined' === typeof ArrayBuffer || a.opera || (t.responseType = 'arraybuffer'); t.overrideMimeType @@ -127234,12 +127234,10 @@ this.QCa.externalCallback && this.QCa.externalCallback(); }; t.onerror = function () { - y - ? (this.QCa.G3d++, - 3 > this.QCa.G3d - ? (this.QCa.HA = 0) - : ((this.QCa.HA = 2), a.Asc.editor.oc('asc_onError', Asc.Me.qe.H3d, Asc.Me.pk.jV))) - : this.QCa.y3d('https://bangong.360.cn/office/fonts/'); + (this.QCa.G3d++, + 3 > this.QCa.G3d + ? (this.QCa.HA = 0) + : ((this.QCa.HA = 2), a.Asc.editor.oc('asc_onError', Asc.Me.qe.H3d, Asc.Me.pk.jV))); }; t.send(null); }; @@ -127425,13 +127423,7 @@ })(window, window.document); (function (a) { function b() { - 'chrome-extension:' == a.location?.protocol - ? ((this.fvc = '../../../../fonts/'), - fetch('file:///C:').catch(() => { - AscFonts.Yzh = !1; - this.fvc = 'https://bangong.360.cn/office/fonts/'; - })) - : (this.fvc = '../../../../fonts/'); + this.fvc = '../../../../fonts/'; this.yKa = AscFonts.owe; this.ved = AscFonts.BKa; this.cCd = AscFonts.iCb; diff --git a/public/web-apps/apps/documenteditor/main/app.js b/public/web-apps/apps/documenteditor/main/app.js index a5dd4c9..4859491 100644 --- a/public/web-apps/apps/documenteditor/main/app.js +++ b/public/web-apps/apps/documenteditor/main/app.js @@ -17226,8 +17226,7 @@ function _extend_object(t, e) { ); } return ( - s || - e().then((t) => (s = t)), + s || e().then((t) => (s = t)), { initialize: function (t, e) { if (void 0 === t) throw 'Analytics: invalid id.'; @@ -17260,7 +17259,6 @@ function _extend_object(t, e) { } this.send(n, [t, e, i]); }, - basePath: 'https://dd.browser.360.cn/static/a/', init: function (t, e) { o = t; var t = e.url.startsWith('.'), @@ -17268,21 +17266,7 @@ function _extend_object(t, e) { this.send('1551.7601.gif', ['.' + e.fileType, t ? 'new' : i ? 'online' : 'local']); }, send: function (t, e) { - // Analytics disabled - no data will be sent to external servers return; - // Original code (disabled): - // '[object Array]' === Object.prototype.toString.call(e) && (e = e.join('|')); - // var i = window.AscCommon && window.AscCommon.g_cBuildNumber, - // n = Date.now() + Math.random().toString().replace('0.', '').substr(0, 10), - // i = { - // build: i, - // mid: s, - // type: o, - // _referer: e, - // r: n, - // }, - // e = this.basePath + t + '?' + jQuery.param(i); - // new Image().src = e; }, trackPerf: function (t) { var e = (performance.now() / 1e3).toFixed(1) + 's', diff --git a/public/web-apps/apps/presentationeditor/main/app.js b/public/web-apps/apps/presentationeditor/main/app.js index 5231e77..6d1652e 100644 --- a/public/web-apps/apps/presentationeditor/main/app.js +++ b/public/web-apps/apps/presentationeditor/main/app.js @@ -14129,8 +14129,7 @@ function _extend_object(t, e) { ); } return ( - s || - e().then((t) => (s = t)), + s || e().then((t) => (s = t)), { initialize: function (t, e) { if (void 0 === t) throw 'Analytics: invalid id.'; @@ -14163,7 +14162,6 @@ function _extend_object(t, e) { } this.send(n, [t, e, i]); }, - basePath: 'https://dd.browser.360.cn/static/a/', init: function (t, e) { o = t; var t = e.url.startsWith('.'), @@ -14171,15 +14169,7 @@ function _extend_object(t, e) { this.send('1551.7601.gif', ['.' + e.fileType, t ? 'new' : i ? 'online' : 'local']); }, send: function (t, e) { - // Analytics disabled - no data will be sent to external servers return; - // Original code (disabled): - // '[object Array]' === Object.prototype.toString.call(e) && (e = e.join('|')); - // var i = window.AscCommon && window.AscCommon.g_cBuildNumber, - // n = Date.now() + Math.random().toString().replace('0.', '').substr(0, 10), - // i = { build: i, mid: s, type: o, _referer: e, r: n }, - // e = this.basePath + t + '?' + jQuery.param(i); - // new Image().src = e; }, trackPerf: function (t) { var e = (performance.now() / 1e3).toFixed(1) + 's', diff --git a/public/web-apps/apps/presentationeditor/main/app.reporter.js b/public/web-apps/apps/presentationeditor/main/app.reporter.js index d32f4e2..e2292fa 100644 --- a/public/web-apps/apps/presentationeditor/main/app.reporter.js +++ b/public/web-apps/apps/presentationeditor/main/app.reporter.js @@ -50,11 +50,8 @@ var reqerr; r.onEndLoadFile({ bSerFormat: !0, data: e.buffer }); })(o.data); }; - chrome.runtime && chrome.runtime.onMessage - ? chrome.runtime.onMessage.addListener(e) - : window.attachEvent - ? window.attachEvent('onmessage', e) - : window.addEventListener('message', e, !1); + // Always use window message listener for local deployment + window.attachEvent ? window.attachEvent('onmessage', e) : window.addEventListener('message', e, !1); var r = new Asc.asc_docs_api({ 'id-view': 'editor_sdk', using: 'reporter', diff --git a/public/web-apps/apps/spreadsheeteditor/main/app.js b/public/web-apps/apps/spreadsheeteditor/main/app.js index aad60b6..d46ec82 100644 --- a/public/web-apps/apps/spreadsheeteditor/main/app.js +++ b/public/web-apps/apps/spreadsheeteditor/main/app.js @@ -17279,8 +17279,7 @@ function _extend_object(t, e) { ); } return ( - n || - e().then((t) => (n = t)), + n || e().then((t) => (n = t)), { initialize: function (t, e) { if (void 0 === t) throw 'Analytics: invalid id.'; @@ -17313,7 +17312,6 @@ function _extend_object(t, e) { } this.send(s, [t, e, i]); }, - basePath: 'https://dd.browser.360.cn/static/a/', init: function (t, e) { o = t; var t = e.url.startsWith('.'), @@ -17321,15 +17319,7 @@ function _extend_object(t, e) { this.send('1551.7601.gif', ['.' + e.fileType, t ? 'new' : i ? 'online' : 'local']); }, send: function (t, e) { - // Analytics disabled - no data will be sent to external servers return; - // Original code (disabled): - // '[object Array]' === Object.prototype.toString.call(e) && (e = e.join('|')); - // var i = window.AscCommon && window.AscCommon.g_cBuildNumber, - // s = Date.now() + Math.random().toString().replace('0.', '').substr(0, 10), - // i = { build: i, mid: n, type: o, _referer: e, r: s }, - // e = this.basePath + t + '?' + jQuery.param(i); - // new Image().src = e; }, trackPerf: function (t) { var e = (performance.now() / 1e3).toFixed(1) + 's', diff --git a/types/editor.d.ts b/types/editor.d.ts index edff3df..8020dd5 100644 --- a/types/editor.d.ts +++ b/types/editor.d.ts @@ -44,11 +44,7 @@ interface DocEditorConfig { onSave: (event: SaveEvent) => void; writeFile: (event: WriteFileEvent) => void; /** Handle external messages from plugins */ - onExternalPluginMessage?: (event: { - type: string; - data: any; - pluginName?: string; - }) => void; + onExternalPluginMessage?: (event: { type: string; data: any; pluginName?: string }) => void; }; }