mirror of https://github.com/xwiki-labs/cryptpad
Integration API: initialize an app from a Blob
This commit is contained in:
parent
8b0d80c0c4
commit
5081d5d3c0
|
@ -128,14 +128,8 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
var importContent = UIElements.importContent = function (type, f, cfg) {
|
var importContent = UIElements.importContent = function (type, f, cfg) {
|
||||||
return function () {
|
return function (_file) {
|
||||||
var $files = $('<input>', {type:"file"});
|
var todo = function (file) {
|
||||||
if (cfg && cfg.accept) {
|
|
||||||
$files.attr('accept', cfg.accept);
|
|
||||||
}
|
|
||||||
$files.click();
|
|
||||||
$files.on('change', function (e) {
|
|
||||||
var file = e.target.files[0];
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
var parsed = file && file.name && /.+\.([^.]+)$/.exec(file.name);
|
var parsed = file && file.name && /.+\.([^.]+)$/.exec(file.name);
|
||||||
var ext = parsed && parsed[1];
|
var ext = parsed && parsed[1];
|
||||||
|
@ -144,7 +138,19 @@ define([
|
||||||
reader.readAsArrayBuffer(file, type);
|
reader.readAsArrayBuffer(file, type);
|
||||||
} else {
|
} else {
|
||||||
reader.readAsText(file, type);
|
reader.readAsText(file, type);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_file) { return void todo(_file); }
|
||||||
|
|
||||||
|
var $files = $('<input>', {type:"file"});
|
||||||
|
if (cfg && cfg.accept) {
|
||||||
|
$files.attr('accept', cfg.accept);
|
||||||
|
}
|
||||||
|
$files.click();
|
||||||
|
$files.on('change', function (e) {
|
||||||
|
var file = e.target.files[0];
|
||||||
|
todo(file);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -627,12 +633,16 @@ define([
|
||||||
});
|
});
|
||||||
|
|
||||||
var handler = data.first? function () {
|
var handler = data.first? function () {
|
||||||
data.first(importer);
|
data.first(function () {
|
||||||
|
importer(); // Make sure we don't pass arguments to importer
|
||||||
|
});
|
||||||
}: importer; //importContent;
|
}: importer; //importContent;
|
||||||
|
|
||||||
button
|
button
|
||||||
.click(common.prepareFeedback(type))
|
.click(common.prepareFeedback(type))
|
||||||
.click(handler);
|
.click(function () {
|
||||||
|
handler();
|
||||||
|
});
|
||||||
//}
|
//}
|
||||||
break;
|
break;
|
||||||
case 'upload':
|
case 'upload':
|
||||||
|
|
|
@ -71,6 +71,7 @@ define([
|
||||||
var evStart = Util.mkEvent(true);
|
var evStart = Util.mkEvent(true);
|
||||||
|
|
||||||
var mediaTagEmbedder;
|
var mediaTagEmbedder;
|
||||||
|
var fileImporter;
|
||||||
var $embedButton;
|
var $embedButton;
|
||||||
|
|
||||||
var common;
|
var common;
|
||||||
|
@ -545,7 +546,8 @@ define([
|
||||||
contentUpdate(newContent, waitFor);
|
contentUpdate(newContent, waitFor);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!cpNfInner.metadataMgr.getPrivateData().isNewFile) {
|
var priv = cpNfInner.metadataMgr.getPrivateData();
|
||||||
|
if (!priv.isNewFile) {
|
||||||
// We're getting 'new pad' but there is an existing file
|
// We're getting 'new pad' but there is an existing file
|
||||||
// We don't know exactly why this can happen but under no circumstances
|
// We don't know exactly why this can happen but under no circumstances
|
||||||
// should we overwrite the content, so lets just try again.
|
// should we overwrite the content, so lets just try again.
|
||||||
|
@ -558,11 +560,16 @@ define([
|
||||||
onCorruptedCache();
|
onCorruptedCache();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (priv.initialState) {
|
||||||
|
var blob = priv.initialState;
|
||||||
|
var file = new File([blob], blob.name);
|
||||||
|
UIElements.importContent('text/plain', fileImporter, {})(file);
|
||||||
|
}
|
||||||
title.updateTitle(title.defaultTitle);
|
title.updateTitle(title.defaultTitle);
|
||||||
evOnDefaultContentNeeded.fire();
|
evOnDefaultContentNeeded.fire();
|
||||||
}
|
}
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
// We have a valid chainpad, reenable cache fix in case with reconnect with
|
// We have a valid chainpad, reenable cache fix in case we reconnect with
|
||||||
// a corrupted cache
|
// a corrupted cache
|
||||||
noCache = false;
|
noCache = false;
|
||||||
|
|
||||||
|
@ -698,31 +705,32 @@ define([
|
||||||
|
|
||||||
var setFileImporter = function (options, fi, async) {
|
var setFileImporter = function (options, fi, async) {
|
||||||
if (readOnly) { return; }
|
if (readOnly) { return; }
|
||||||
toolbar.$drawer.append(
|
fileImporter = function (c, f) {
|
||||||
common.createButton('import', true, options, function (c, f) {
|
if (state !== STATE.READY || unsyncMode) {
|
||||||
if (state !== STATE.READY || unsyncMode) {
|
return void UI.warn(Messages.disconnected);
|
||||||
return void UI.warn(Messages.disconnected);
|
}
|
||||||
}
|
if (async) {
|
||||||
if (async) {
|
fi(c, f, function (content) {
|
||||||
fi(c, f, function (content) {
|
nThen(function (waitFor) {
|
||||||
nThen(function (waitFor) {
|
contentUpdate(content, waitFor);
|
||||||
contentUpdate(content, waitFor);
|
}).nThen(function () {
|
||||||
}).nThen(function () {
|
onLocal();
|
||||||
onLocal();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
nThen(function (waitFor) {
|
|
||||||
var content = fi(c, f);
|
|
||||||
if (typeof(content) === "undefined") {
|
|
||||||
return void UI.warn(Messages.importError);
|
|
||||||
}
|
|
||||||
contentUpdate(content, waitFor);
|
|
||||||
}).nThen(function () {
|
|
||||||
onLocal();
|
|
||||||
});
|
});
|
||||||
})
|
return;
|
||||||
|
}
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
var content = fi(c, f);
|
||||||
|
if (typeof(content) === "undefined") {
|
||||||
|
return void UI.warn(Messages.importError);
|
||||||
|
}
|
||||||
|
contentUpdate(content, waitFor);
|
||||||
|
}).nThen(function () {
|
||||||
|
onLocal();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
toolbar.$drawer.append(
|
||||||
|
common.createButton('import', true, options, fileImporter)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,8 @@ define([
|
||||||
href: href,
|
href: href,
|
||||||
useCreationScreen: !isIntegration,
|
useCreationScreen: !isIntegration,
|
||||||
messaging: true,
|
messaging: true,
|
||||||
integration: isIntegration
|
integration: isIntegration,
|
||||||
|
initialState: integration.initialState || undefined
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -353,6 +353,13 @@ define([
|
||||||
delete sessionStorage.CP_formExportSheet;
|
delete sessionStorage.CP_formExportSheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New integrated pad
|
||||||
|
if (cfg.initialState) {
|
||||||
|
currentPad.href = cfg.href;
|
||||||
|
currentPad.hash = cfg.hash;
|
||||||
|
return void todo();
|
||||||
|
}
|
||||||
|
|
||||||
// New pad options
|
// New pad options
|
||||||
var options = parsed.getOptions();
|
var options = parsed.getOptions();
|
||||||
if (options.newPadOpts) {
|
if (options.newPadOpts) {
|
||||||
|
@ -697,7 +704,6 @@ define([
|
||||||
burnAfterReading: burnAfterReading,
|
burnAfterReading: burnAfterReading,
|
||||||
storeInTeam: Cryptpad.initialTeam || (Cryptpad.initialPath ? -1 : undefined),
|
storeInTeam: Cryptpad.initialTeam || (Cryptpad.initialPath ? -1 : undefined),
|
||||||
supportsWasm: Utils.Util.supportsWasm(),
|
supportsWasm: Utils.Util.supportsWasm(),
|
||||||
integration: cfg.integration
|
|
||||||
};
|
};
|
||||||
if (window.CryptPad_newSharedFolder) {
|
if (window.CryptPad_newSharedFolder) {
|
||||||
additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder;
|
additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder;
|
||||||
|
@ -718,6 +724,12 @@ define([
|
||||||
additionalPriv.isChannelMuted = true;
|
additionalPriv.isChannelMuted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Integration
|
||||||
|
additionalPriv.integration = cfg.integration;
|
||||||
|
additionalPriv.initialState = cfg.initialState instanceof Blob ?
|
||||||
|
cfg.initialState : undefined;
|
||||||
|
|
||||||
|
// Early access
|
||||||
var priv = metaObj.priv;
|
var priv = metaObj.priv;
|
||||||
var _plan = typeof(priv.plan) === "undefined" ? Utils.LocalStore.getPremium() : priv.plan;
|
var _plan = typeof(priv.plan) === "undefined" ? Utils.LocalStore.getPremium() : priv.plan;
|
||||||
var p = Utils.Util.checkRestrictedApp(parsed.type, AppConfig,
|
var p = Utils.Util.checkRestrictedApp(parsed.type, AppConfig,
|
||||||
|
@ -729,6 +741,7 @@ define([
|
||||||
additionalPriv.earlyAccessBlocked = true;
|
additionalPriv.earlyAccessBlocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safe apps
|
||||||
if (isSafe) {
|
if (isSafe) {
|
||||||
additionalPriv.hashes = hashes;
|
additionalPriv.hashes = hashes;
|
||||||
additionalPriv.password = password;
|
additionalPriv.password = password;
|
||||||
|
@ -744,7 +757,7 @@ define([
|
||||||
Utils.LocalStore.setPremium(metaObj.priv.plan);
|
Utils.LocalStore.setPremium(metaObj.priv.plan);
|
||||||
}
|
}
|
||||||
|
|
||||||
sframeChan.event('EV_METADATA_UPDATE', metaObj);
|
sframeChan.event('EV_METADATA_UPDATE', metaObj, {raw: true});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Cryptpad.onMetadataChanged(updateMeta);
|
Cryptpad.onMetadataChanged(updateMeta);
|
||||||
|
@ -1994,6 +2007,15 @@ define([
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we add the validateKey to channel metadata when we don't use
|
||||||
|
// the pad creation screen
|
||||||
|
if (!rtConfig.metadata && secret.keys.validateKey) {
|
||||||
|
rtConfig.metadata = {
|
||||||
|
validateKey: secret.keys.validateKey
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var cpNfCfg = {
|
var cpNfCfg = {
|
||||||
sframeChan: sframeChan,
|
sframeChan: sframeChan,
|
||||||
channel: secret.channel,
|
channel: secret.channel,
|
||||||
|
@ -2021,6 +2043,8 @@ define([
|
||||||
Cryptpad.getMetadata(waitFor(function (err, m) {
|
Cryptpad.getMetadata(waitFor(function (err, m) {
|
||||||
cpNfCfg.owners = [m.priv.edPublic];
|
cpNfCfg.owners = [m.priv.edPublic];
|
||||||
}));
|
}));
|
||||||
|
} else if (isNewFile && !cfg.useCreationScreen && cfg.initialState) {
|
||||||
|
console.log('new file with initial state provided');
|
||||||
} else if (isNewFile && !cfg.useCreationScreen && currentPad.hash) {
|
} else if (isNewFile && !cfg.useCreationScreen && currentPad.hash) {
|
||||||
console.log("new file with hash in the address bar in an app without pcs and which requires owners");
|
console.log("new file with hash in the address bar in an app without pcs and which requires owners");
|
||||||
sframeChan.onReady(function () {
|
sframeChan.onReady(function () {
|
||||||
|
|
|
@ -426,6 +426,9 @@ define([
|
||||||
funcs.handleNewFile = function (waitFor, config) {
|
funcs.handleNewFile = function (waitFor, config) {
|
||||||
if (window.__CRYPTPAD_TEST__) { return; }
|
if (window.__CRYPTPAD_TEST__) { return; }
|
||||||
var priv = ctx.metadataMgr.getPrivateData();
|
var priv = ctx.metadataMgr.getPrivateData();
|
||||||
|
if (priv.isNewFile && priv.initialState) {
|
||||||
|
return void setTimeout(waitFor());
|
||||||
|
}
|
||||||
if (priv.isNewFile) {
|
if (priv.isNewFile) {
|
||||||
var c = (priv.settings.general && priv.settings.general.creation) || {};
|
var c = (priv.settings.general && priv.settings.general.creation) || {};
|
||||||
// If this is a new file but we have a hash in the URL and pad creation screen is
|
// If this is a new file but we have a hash in the URL and pad creation screen is
|
||||||
|
|
|
@ -78,11 +78,30 @@
|
||||||
config.events.onSave(data);
|
config.events.onSave(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
var onKeyValidated = function () {
|
var getBlob = function (cb) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', config.document.url, true);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
xhr.onload = function(e) {
|
||||||
|
if (this.status == 200) {
|
||||||
|
var blob = this.response;
|
||||||
|
// myBlob is now the blob that the object URL pointed to.
|
||||||
|
cb(null, blob);
|
||||||
|
} else {
|
||||||
|
cb(this.status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function (e) {
|
||||||
|
cb(e.message);
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
};
|
||||||
|
|
||||||
|
var start = function (blob) {
|
||||||
chan.send('START', {
|
chan.send('START', {
|
||||||
key: key,
|
key: key,
|
||||||
application: config.documentType,
|
application: config.documentType,
|
||||||
document: config.document.url,
|
document: blob,
|
||||||
}, function (obj) {
|
}, function (obj) {
|
||||||
if (obj && obj.error) { reject(obj.error); return console.error(obj.error); }
|
if (obj && obj.error) { reject(obj.error); return console.error(obj.error); }
|
||||||
console.log('OUTER START SUCCESS');
|
console.log('OUTER START SUCCESS');
|
||||||
|
@ -90,6 +109,14 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var onKeyValidated = function () {
|
||||||
|
getBlob(function (err, blob) {
|
||||||
|
if (err) { reject(err); return console.error(err); }
|
||||||
|
blob.name = `document.${config.document.fileType}`;
|
||||||
|
start(blob);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
chan.send('GET_SESSION', {
|
chan.send('GET_SESSION', {
|
||||||
key: key
|
key: key
|
||||||
}, function (obj) {
|
}, function (obj) {
|
||||||
|
@ -113,6 +140,7 @@
|
||||||
* @param {object} config The object containing configuration parameters.
|
* @param {object} config The object containing configuration parameters.
|
||||||
* @param {object} config.document The document to load.
|
* @param {object} config.document The document to load.
|
||||||
* @param {string} document.url The document URL.
|
* @param {string} document.url The document URL.
|
||||||
|
* @param {string} document.fileType The document extension (md, xml, html, etc.).
|
||||||
* @param {string} document.key The collaborative session key.
|
* @param {string} document.key The collaborative session key.
|
||||||
* @param {object} config.events Event handlers.
|
* @param {object} config.events Event handlers.
|
||||||
* @param {function} events.onSave The save function to store the document when edited.
|
* @param {function} events.onSave The save function to store the document when edited.
|
||||||
|
@ -137,7 +165,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config) { return reject('Missing args: no data provided'); }
|
if (!config) { return reject('Missing args: no data provided'); }
|
||||||
['document.url', 'document.key', 'documentType',
|
if(['document.url', 'document.fileType', 'document.key', 'documentType',
|
||||||
'events.onSave', 'events.onNewKey'].some(function (k) {
|
'events.onSave', 'events.onNewKey'].some(function (k) {
|
||||||
var s = k.split('.');
|
var s = k.split('.');
|
||||||
var c = config;
|
var c = config;
|
||||||
|
@ -148,7 +176,7 @@
|
||||||
}
|
}
|
||||||
c = c[key];
|
c = c[key];
|
||||||
});
|
});
|
||||||
});
|
})) { return; }
|
||||||
|
|
||||||
cryptpadURL = cryptpadURL.replace(/(\/)+$/, '');
|
cryptpadURL = cryptpadURL.replace(/(\/)+$/, '');
|
||||||
var url = cryptpadURL + '/integration/';
|
var url = cryptpadURL + '/integration/';
|
||||||
|
|
|
@ -99,7 +99,7 @@ define([
|
||||||
isNew = true;
|
isNew = true;
|
||||||
return Hash.createRandomHash('integration');
|
return Hash.createRandomHash('integration');
|
||||||
};
|
};
|
||||||
var oldKey = data.sessionKey;
|
var oldKey = data.key;
|
||||||
if (!oldKey) { return void cb({ key: getHash() }); }
|
if (!oldKey) { return void cb({ key: getHash() }); }
|
||||||
|
|
||||||
checkSession(oldKey, function (obj) {
|
checkSession(oldKey, function (obj) {
|
||||||
|
@ -112,33 +112,17 @@ define([
|
||||||
|
|
||||||
chan.on('START', function (data) {
|
chan.on('START', function (data) {
|
||||||
console.warn('INNER START', data);
|
console.warn('INNER START', data);
|
||||||
nThen(function (w) {
|
var href = Hash.hashToHref(data.key, data.application);
|
||||||
if (!isNew) { return; }
|
console.error(Hash.hrefToHexChannelId(href));
|
||||||
|
window.CP_integration_outer = {
|
||||||
// XXX initial content TBD
|
pathname: `/${data.application}/`,
|
||||||
var content = JSON.stringify({
|
hash: data.key,
|
||||||
content: data.document,
|
href: href,
|
||||||
highlightMode: "gfm"
|
initialState: isNew ? data.document : undefined
|
||||||
}); // XXX only for code
|
};
|
||||||
|
require(['/common/sframe-app-outer.js'], function () {
|
||||||
console.error('CRYPTPUT', data.key);
|
console.warn('SAO REQUIRED');
|
||||||
Crypt.put(data.key, content, w(), {
|
delete window.CP_integration_outer;
|
||||||
metadata: {
|
|
||||||
selfdestruct: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).nThen(function () {
|
|
||||||
var href = Hash.hashToHref(data.key, data.application);
|
|
||||||
console.error(Hash.hrefToHexChannelId(href));
|
|
||||||
window.CP_integration_outer = {
|
|
||||||
pathname: `/${data.application}/`,
|
|
||||||
hash: data.key,
|
|
||||||
href: href
|
|
||||||
};
|
|
||||||
require(['/common/sframe-app-outer.js'], function () {
|
|
||||||
console.warn('SAO REQUIRED');
|
|
||||||
delete window.CP_integration_outer;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue