mirror of
https://github.com/ONLYOFFICE/sdkjs.git
synced 2025-04-18 14:24:11 +03:00
[se] Support auto update external links Co-authored-by: GoshaZotov <Igor.Zotov@onlyoffice.com> Co-committed-by: GoshaZotov <Igor.Zotov@onlyoffice.com>
251 lines
8.7 KiB
JavaScript
251 lines
8.7 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* This program is a free software product. You can redistribute it and/or
|
||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||
* version 3 as published by the Free Software Foundation. In accordance with
|
||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||
* of any third-party rights.
|
||
*
|
||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||
*
|
||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||
* street, Riga, Latvia, EU, LV-1050.
|
||
*
|
||
* The interactive user interfaces in modified source and object code versions
|
||
* of the Program must display Appropriate Legal Notices, as required under
|
||
* Section 5 of the GNU AGPL version 3.
|
||
*
|
||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||
* grant you any rights under trademark law for use of our trademarks.
|
||
*
|
||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||
* well as technical writing content are licensed under the terms of the
|
||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||
*
|
||
*/
|
||
|
||
"use strict";
|
||
|
||
(function (window) {
|
||
function CExternalDataLoader(arrExternalReference, oApi, fCallback) {
|
||
this.externalReferences = arrExternalReference || [];
|
||
this.api = oApi;
|
||
this.isLocalDesktop = window["AscDesktopEditor"] && window["AscDesktopEditor"]["IsLocalFile"]();
|
||
this.fCallback = fCallback;
|
||
}
|
||
|
||
CExternalDataLoader.prototype.updateExternalData = function () {
|
||
if (this.externalReferences) {
|
||
if (this.isLocalDesktop) {
|
||
this.resolveUpdateData();
|
||
} else {
|
||
this.api.sendEvent("asc_onUpdateExternalReference", this.externalReferences, this.tryForceSave.bind(this));
|
||
}
|
||
}
|
||
};
|
||
CExternalDataLoader.prototype.tryForceSave = function (arrData) {
|
||
arrData = arrData || [];
|
||
const oThis = this;
|
||
const nTimeout = 10000;
|
||
const arrPromises = [];
|
||
let isForceSavePossible = true;
|
||
for (let i = 0; i < arrData.length; i++) {
|
||
const oData = arrData[i];
|
||
const sToken = oData['token'];
|
||
const sKey = oData['key'];
|
||
|
||
//check updated file on server. compare keys. if file not updated - check only collaborative editing
|
||
let curEr = oThis.externalReferences[i].externalReference;
|
||
let curErKey = curEr.getKey();
|
||
oData.notChangedFile = sKey === curEr.getKey();
|
||
if (curErKey == null) {
|
||
curEr.setKey(sKey);
|
||
}
|
||
|
||
if (!sKey) {
|
||
//if don't have key, then don't have force save
|
||
isForceSavePossible = false;
|
||
break;
|
||
}
|
||
|
||
const oForceUpdatePromise = new Promise(function (fResolve) {
|
||
oThis.api.saveRelativeFromChanges(sKey, sToken, nTimeout, function (bTimeout, oResult) {
|
||
//oResult -> {code, inProgress, url}
|
||
|
||
//errors
|
||
//oResult.code -> c_oAscServerCommandErrors
|
||
//c_oAscServerCommandErrors.NoError - everything all right
|
||
//c_oAscServerCommandErrors.NotModified - no file, no changes
|
||
//c_oAscServerCommandErrors.Token - wrong token
|
||
//inProgress && с c_oAscServerCommandErrors.NoError -> the function was called several times and did'nt wait answer
|
||
|
||
//url - file link
|
||
|
||
if (!bTimeout && oResult["code"] === AscCommon.c_oAscServerCommandErrors.NoError) {
|
||
arrData[i]["directUrl"] = oResult["url"];
|
||
arrData[i]["url"] = oResult["url"];
|
||
arrData[i]["fileType"] = "xlsx";
|
||
arrData[i]["token"] = null;
|
||
arrData[i].notChangedFile = false;
|
||
}
|
||
fResolve();
|
||
});
|
||
});
|
||
arrPromises.push(oForceUpdatePromise);
|
||
}
|
||
if (!isForceSavePossible) {
|
||
oThis.resolveUpdateData(arrData);
|
||
} else {
|
||
Promise.all(arrPromises).then(function () {
|
||
oThis.resolveUpdateData(arrData);
|
||
});
|
||
}
|
||
};
|
||
CExternalDataLoader.prototype.resolveUpdateData = function (arrData) {
|
||
arrData = arrData || [];
|
||
const nLength = Math.max(arrData.length, this.externalReferences.length);
|
||
const arrFPromiseGetters = [];
|
||
for (let i = 0; i < nLength; i += 1) {
|
||
if (this.isLocalDesktop || (arrData[i] && !arrData[i]["error"] && !arrData[i].notChangedFile)) {
|
||
const oPromiseGetter = new CExternalDataPromiseGetter(this.api, this.getExternalReference(i), arrData[i]);
|
||
arrFPromiseGetters.push(oPromiseGetter.getPromise.bind(oPromiseGetter));
|
||
}
|
||
}
|
||
this.doUpdate(arrFPromiseGetters);
|
||
};
|
||
CExternalDataLoader.prototype.doUpdate = function (arrFPromiseGetters) {
|
||
const oThis = this;
|
||
const oPromiseGetterIterator = new AscCommon.CPromiseGetterIterator(arrFPromiseGetters);
|
||
oPromiseGetterIterator.forAllSuccessValues(function (arrValues) {
|
||
oThis.fCallback(arrValues);
|
||
});
|
||
};
|
||
CExternalDataLoader.prototype.getExternalReference = function (nId) {
|
||
if (this.externalReferences[nId]) {
|
||
return this.externalReferences[nId].asc_getPath();
|
||
}
|
||
};
|
||
|
||
function CExternalDataPromiseGetter(oApi, sExternalReference, oData) {
|
||
this.externalReference = sExternalReference;
|
||
this.data = oData;
|
||
this.api = oApi;
|
||
this.fileUrl = this.getFileUrl();
|
||
}
|
||
|
||
CExternalDataPromiseGetter.prototype.isLocalDesktop = function () {
|
||
return window["AscDesktopEditor"] && window["AscDesktopEditor"]["IsLocalFile"]();
|
||
};
|
||
CExternalDataPromiseGetter.prototype.resolveStream = function (arrStream, fResolve) {
|
||
fResolve({stream: arrStream, externalReferenceId: this.externalReference, data: this.data});
|
||
};
|
||
CExternalDataPromiseGetter.prototype.getLocalDesktopPromise = function () {
|
||
const oThis = this;
|
||
return new Promise(function (resolve) {
|
||
if (oThis.fileUrl) {
|
||
window["AscDesktopEditor"]["convertFile"](oThis.fileUrl, 0x2002, function (_file) {
|
||
let arrStream = null;
|
||
if (_file) {
|
||
arrStream = new Uint8Array(_file["get"]());
|
||
_file["close"]();
|
||
}
|
||
oThis.resolveStream(arrStream, resolve);
|
||
});
|
||
} else {
|
||
oThis.resolveStream(null, resolve);
|
||
}
|
||
});
|
||
};
|
||
|
||
CExternalDataPromiseGetter.prototype.getLocalFileLink = function () {
|
||
let res = this.externalReference;
|
||
// todo should we make .replace to the local link here?
|
||
if (res) {
|
||
res = res.replace(/^file:\/\/\//, '');
|
||
res = res.replace(/^file:\/\//, '');
|
||
}
|
||
return res;
|
||
};
|
||
|
||
CExternalDataPromiseGetter.prototype.isExternalLink = function () {
|
||
const p = /^(?:http:|https:)/;
|
||
return this.externalReference.match(p);
|
||
};
|
||
|
||
CExternalDataPromiseGetter.prototype.getFileUrl = function () {
|
||
if (this.isLocalDesktop() && !this.isExternalLink()) {
|
||
return this.getLocalFileLink();
|
||
} else if (this.data && !this.data["error"]) {
|
||
return this.data["url"];
|
||
}
|
||
return this.externalReference;
|
||
};
|
||
CExternalDataPromiseGetter.prototype.isSupportOOXML = function () {
|
||
return this.api["asc_isSupportFeature"]("ooxml");
|
||
};
|
||
CExternalDataPromiseGetter.prototype.getPromise = function () {
|
||
const oThis = this;
|
||
if (this.isLocalDesktop()) {
|
||
return this.getLocalDesktopPromise();
|
||
} else if (!window["NATIVE_EDITOR_ENJINE"]) {
|
||
return this.getSDKPromise();
|
||
} else {
|
||
return new Promise(function (fResolve) {
|
||
oThis.resolveStream(null, fResolve);
|
||
});
|
||
}
|
||
};
|
||
|
||
CExternalDataPromiseGetter.prototype.loadFileContentFromUrl = function (sFileUrl, resolve) {
|
||
const oThis = this;
|
||
AscCommon.loadFileContent(sFileUrl, function (httpRequest) {
|
||
let arrStream = null;
|
||
if (httpRequest) {
|
||
arrStream = AscCommon.initStreamFromResponse(httpRequest);
|
||
}
|
||
oThis.resolveStream(arrStream, resolve);
|
||
}, "arraybuffer");
|
||
};
|
||
|
||
CExternalDataPromiseGetter.prototype.getSDKPromise = function () {
|
||
const oThis = this;
|
||
return new Promise(function (fResolve) {
|
||
const isSupportOOXML = oThis.isSupportOOXML();
|
||
const nOutputFormat = isSupportOOXML ? Asc.c_oAscFileType.XLSX : Asc.c_oAscFileType.XLSY;
|
||
const sFileUrl = oThis.getFileUrl();
|
||
const sFileType = oThis.data["fileType"];
|
||
const sToken = oThis.data["token"];
|
||
const sDirectUrl = oThis.data["directUrl"];
|
||
const bIsXLSX = sFileType === "xlsx";
|
||
|
||
if ((sFileUrl && !bIsXLSX) || !isSupportOOXML) {
|
||
let bLoad = false;
|
||
oThis.api.getConvertedXLSXFileFromUrl(sFileUrl, sFileType, sToken, nOutputFormat,
|
||
function (sFileUrlAfterConvert) {
|
||
if (sFileUrlAfterConvert) {
|
||
oThis.loadFileContentFromUrl(sFileUrlAfterConvert, fResolve);
|
||
bLoad = true;
|
||
} else if (!bLoad) {
|
||
oThis.resolveStream(null, fResolve);
|
||
}
|
||
});
|
||
} else if (sDirectUrl || sFileUrl) {
|
||
oThis.api._downloadOriginalFile(sDirectUrl, sFileUrl, sFileType, sToken, function (arrStream) {
|
||
oThis.resolveStream(arrStream, fResolve);
|
||
});
|
||
} else {
|
||
oThis.resolveStream(null, fResolve);
|
||
}
|
||
});
|
||
};
|
||
|
||
AscCommon.CExternalDataLoader = CExternalDataLoader;
|
||
})(window);
|
||
|