Merge pull request #2139 from cryptpad/api-fixes

Integration API improvements
This commit is contained in:
yflory 2026-01-09 17:32:57 +01:00 committed by GitHub
commit c52ff0af4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 78 additions and 6 deletions

View File

@ -6,12 +6,18 @@ define([
'jquery',
'/common/hyperscript.js',
'/customize/pages.js',
'/customize/application_config.js',
'/components/nthen/index.js',
], function ($, h, Pages, nThen) {
], function ($, h, Pages, AppConfig, nThen) {
// we consider that there is no valid reason to load any of the info pages
// in an iframe. abort everything if you detect that you are embedded.
if (window.top !== window) { return; }
if (AppConfig.integrationOnly) {
window.location.href = '/customize/404.html';
return;
}
$(function () {
var $body = $('body');
var pathname = location.pathname;

View File

@ -233,6 +233,11 @@ const factory = () => {
// NOTE: this is only enforced client-side and will not prevent malicious clients from storing data
AppConfig.disableAnonymousPadCreation = false;
// If your application is meant to be used exclusively with the
// integration API, you can disable the direct access to the app by
// setting integrationOnly to true
AppConfig.integrationOnly = false;
// Hide the usage bar in settings and drive
//AppConfig.hideUsageBar = true;

View File

@ -1913,6 +1913,9 @@ define([
mediasData: mediasData
}, function (err, obj) {
if (err || !obj || !obj.data) {
if (integrationChannel) {
integrationChannel.event('EV_INTEGRATION_ERROR', 'X2T_ERROR');
}
UI.alert(Messages.oo_couldNotConvertDocument, cb);
return;
}
@ -1969,6 +1972,9 @@ define([
const onError = function() {
console.error(arguments);
if (integrationChannel) {
integrationChannel.event('EV_INTEGRATION_ERROR', 'DOCUMENT_ERROR');
}
if (APP.isDownload) {
var sframeChan = common.getSframeChannel();
sframeChan.event('EV_OOIFRAME_DONE', '');
@ -2074,9 +2080,7 @@ define([
delete APP.oldCursor;
}
if (integrationChannel) {
APP.onDocumentUnlock = () => {
integrationChannel.event('EV_INTEGRATION_READY');
};
integrationChannel.event('EV_INTEGRATION_READY');
}
}
delete APP.startNew;
@ -2382,7 +2386,7 @@ define([
if (ec.editorConfig?.customization?.goback) {
c.goback.blank = true;
}
if (!privateData?.integrationConfig?.autosave) {
if (typeof(privateData?.integrationConfig?.autosave) !== "number") {
c.forcesave = true;
}
}
@ -3706,6 +3710,11 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
cb();
});
});
integrationChannel.on('EV_INTEGRATION_MANUAL_SAVE', function () {
integrationSave(function () {
console.log('Integration manual save');
});
});
/* test button
if (!cfg.autosave) {

View File

@ -662,6 +662,11 @@ define([
cb();
});
});
integrationChannel.on('EV_INTEGRATION_MANUAL_SAVE', function () {
integrationSave(function () {
console.log('Integration manual save');
});
});
}
}

View File

@ -837,6 +837,10 @@ define([
!Utils.PadTypes.isAvailable(parsed.type)) {
additionalPriv.disabledApp = true;
}
if (AppConfig.integrationOnly && !cfg.integration) {
additionalPriv.disabledApp = true;
}
if (!Utils.LocalStore.isLoggedIn() &&
AppConfig.registeredOnlyTypes.indexOf(parsed.type) !== -1 &&
parsed.type !== "file") {
@ -2122,6 +2126,11 @@ define([
cfg.integrationUtils.onHasUnsavedChanges(obj, cb);
}
});
sframeChan.on('Q_INTEGRATION_ERROR', function (obj) {
if (cfg.integrationUtils && cfg.integrationUtils.onError) {
cfg.integrationUtils.onError(obj);
}
});
sframeChan.on('Q_INTEGRATION_ON_INSERT_IMAGE', function (data, cb) {
if (cfg.integrationUtils && cfg.integrationUtils.onInsertImage) {
cfg.integrationUtils.onInsertImage(data, cb);
@ -2136,6 +2145,11 @@ define([
cfg.integrationUtils.setDownloadAs(format => {
sframeChan.event('EV_INTEGRATION_DOWNLOADAS', format);
});
if (cfg.integrationUtils.setSave) {
cfg.integrationUtils.setSave(() => {
sframeChan.event('EV_INTEGRATION_MANUAL_SAVE');
});
}
}
}

View File

@ -126,6 +126,7 @@
var start = function () {
//config.document.key = key;
const autosave = typeof(config.autosave) === "number" ? config.autosave : 10;
chan.send('START', {
key: key,
application: config.documentType,
@ -134,7 +135,7 @@
documentKey: docID,
document: blob,
ext: config.document.fileType,
autosave: config.events.onSave && (config.autosave || 10),
autosave: config.events.onSave && autosave,
readOnly: config.mode === 'view',
editorConfig: config.editorConfig || {},
_config: serializedConfig()
@ -216,6 +217,12 @@
});
});
chan.on('DOCUMENT_ERROR', function (err) {
if (config.events.onError) {
config.events.onError(err);
}
});
chan.on('ON_DOWNLOADAS', blob => {
let url = URL.createObjectURL(blob);
if (!config.events.onDownloadAs) { return; }
@ -383,6 +390,15 @@
chan.send('DOWNLOAD_AS', arg);
};
ret.save = () => {
if (!chan) {
return void onDocumentReady.push(() => {
ret.save();
});
}
chan.send('MANUAL_SAVE');
};
return ret;
};

View File

@ -138,6 +138,9 @@ define([
var onInsertImage = function (data, cb) {
chan.send('ON_INSERT_IMAGE', data, cb);
};
var onError = function (err) {
chan.send('DOCUMENT_ERROR', err);
};
var onReady = function () {
chan.send('DOCUMENT_READY', {});
};
@ -157,6 +160,18 @@ define([
chan.send('ON_DOWNLOADAS', blob);
};
let manualSave;
chan.on('MANUAL_SAVE', function (format) {
if (typeof(manualSave) !== "function") {
console.error('UNSUPPORTED COMMAND', 'save');
return;
}
manualSave();
});
let setSave = f => {
manualSave = f;
};
let getInstanceURL = function () {
return Config.httpUnsafeOrigin;
@ -254,9 +269,11 @@ define([
_: data._config
},
utils: {
onError,
onReady: onReady,
onDownloadAs,
setDownloadAs,
setSave,
save: save,
reload: reload,
onHasUnsavedChanges: onHasUnsavedChanges,