diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js
index 1a574cc4c..4127fb568 100644
--- a/www/common/common-ui-elements.js
+++ b/www/common/common-ui-elements.js
@@ -128,14 +128,8 @@ define([
};
var importContent = UIElements.importContent = function (type, f, cfg) {
- return function () {
- var $files = $('', {type:"file"});
- if (cfg && cfg.accept) {
- $files.attr('accept', cfg.accept);
- }
- $files.click();
- $files.on('change', function (e) {
- var file = e.target.files[0];
+ return function (_file) {
+ var todo = function (file) {
var reader = new FileReader();
var parsed = file && file.name && /.+\.([^.]+)$/.exec(file.name);
var ext = parsed && parsed[1];
@@ -144,7 +138,19 @@ define([
reader.readAsArrayBuffer(file, type);
} else {
reader.readAsText(file, type);
- }
+ }
+ };
+
+ if (_file) { return void todo(_file); }
+
+ var $files = $('', {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 () {
- data.first(importer);
+ data.first(function () {
+ importer(); // Make sure we don't pass arguments to importer
+ });
}: importer; //importContent;
button
.click(common.prepareFeedback(type))
- .click(handler);
+ .click(function () {
+ handler();
+ });
//}
break;
case 'upload':
diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js
index 04821ce15..98f66463d 100644
--- a/www/common/sframe-app-framework.js
+++ b/www/common/sframe-app-framework.js
@@ -71,6 +71,7 @@ define([
var evStart = Util.mkEvent(true);
var mediaTagEmbedder;
+ var fileImporter;
var $embedButton;
var common;
@@ -545,7 +546,8 @@ define([
contentUpdate(newContent, waitFor);
}
} 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 don't know exactly why this can happen but under no circumstances
// should we overwrite the content, so lets just try again.
@@ -558,11 +560,16 @@ define([
onCorruptedCache();
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);
evOnDefaultContentNeeded.fire();
}
}).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
noCache = false;
@@ -698,31 +705,32 @@ define([
var setFileImporter = function (options, fi, async) {
if (readOnly) { return; }
- toolbar.$drawer.append(
- common.createButton('import', true, options, function (c, f) {
- if (state !== STATE.READY || unsyncMode) {
- return void UI.warn(Messages.disconnected);
- }
- if (async) {
- fi(c, f, function (content) {
- nThen(function (waitFor) {
- contentUpdate(content, waitFor);
- }).nThen(function () {
- onLocal();
- });
+ fileImporter = function (c, f) {
+ if (state !== STATE.READY || unsyncMode) {
+ return void UI.warn(Messages.disconnected);
+ }
+ if (async) {
+ fi(c, f, function (content) {
+ nThen(function (waitFor) {
+ 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();
});
- })
+ 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)
);
};
diff --git a/www/common/sframe-app-outer.js b/www/common/sframe-app-outer.js
index 38e21f108..c04a99237 100644
--- a/www/common/sframe-app-outer.js
+++ b/www/common/sframe-app-outer.js
@@ -28,7 +28,8 @@ define([
href: href,
useCreationScreen: !isIntegration,
messaging: true,
- integration: isIntegration
+ integration: isIntegration,
+ initialState: integration.initialState || undefined
});
});
});
diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js
index 54ae897ba..ca05bfdfb 100644
--- a/www/common/sframe-common-outer.js
+++ b/www/common/sframe-common-outer.js
@@ -353,6 +353,13 @@ define([
delete sessionStorage.CP_formExportSheet;
}
+ // New integrated pad
+ if (cfg.initialState) {
+ currentPad.href = cfg.href;
+ currentPad.hash = cfg.hash;
+ return void todo();
+ }
+
// New pad options
var options = parsed.getOptions();
if (options.newPadOpts) {
@@ -697,7 +704,6 @@ define([
burnAfterReading: burnAfterReading,
storeInTeam: Cryptpad.initialTeam || (Cryptpad.initialPath ? -1 : undefined),
supportsWasm: Utils.Util.supportsWasm(),
- integration: cfg.integration
};
if (window.CryptPad_newSharedFolder) {
additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder;
@@ -718,6 +724,12 @@ define([
additionalPriv.isChannelMuted = true;
}
+ // Integration
+ additionalPriv.integration = cfg.integration;
+ additionalPriv.initialState = cfg.initialState instanceof Blob ?
+ cfg.initialState : undefined;
+
+ // Early access
var priv = metaObj.priv;
var _plan = typeof(priv.plan) === "undefined" ? Utils.LocalStore.getPremium() : priv.plan;
var p = Utils.Util.checkRestrictedApp(parsed.type, AppConfig,
@@ -729,6 +741,7 @@ define([
additionalPriv.earlyAccessBlocked = true;
}
+ // Safe apps
if (isSafe) {
additionalPriv.hashes = hashes;
additionalPriv.password = password;
@@ -744,7 +757,7 @@ define([
Utils.LocalStore.setPremium(metaObj.priv.plan);
}
- sframeChan.event('EV_METADATA_UPDATE', metaObj);
+ sframeChan.event('EV_METADATA_UPDATE', metaObj, {raw: true});
});
};
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 = {
sframeChan: sframeChan,
channel: secret.channel,
@@ -2021,6 +2043,8 @@ define([
Cryptpad.getMetadata(waitFor(function (err, m) {
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) {
console.log("new file with hash in the address bar in an app without pcs and which requires owners");
sframeChan.onReady(function () {
diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js
index 87054a887..f1705d694 100644
--- a/www/common/sframe-common.js
+++ b/www/common/sframe-common.js
@@ -426,6 +426,9 @@ define([
funcs.handleNewFile = function (waitFor, config) {
if (window.__CRYPTPAD_TEST__) { return; }
var priv = ctx.metadataMgr.getPrivateData();
+ if (priv.isNewFile && priv.initialState) {
+ return void setTimeout(waitFor());
+ }
if (priv.isNewFile) {
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
diff --git a/www/cryptpad-api.js b/www/cryptpad-api.js
index 840311567..7e70a4c0f 100644
--- a/www/cryptpad-api.js
+++ b/www/cryptpad-api.js
@@ -78,11 +78,30 @@
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', {
key: key,
application: config.documentType,
- document: config.document.url,
+ document: blob,
}, function (obj) {
if (obj && obj.error) { reject(obj.error); return console.error(obj.error); }
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', {
key: key
}, function (obj) {
@@ -113,6 +140,7 @@
* @param {object} config The object containing configuration parameters.
* @param {object} config.document The document to load.
* @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 {object} config.events Event handlers.
* @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'); }
- ['document.url', 'document.key', 'documentType',
+ if(['document.url', 'document.fileType', 'document.key', 'documentType',
'events.onSave', 'events.onNewKey'].some(function (k) {
var s = k.split('.');
var c = config;
@@ -148,7 +176,7 @@
}
c = c[key];
});
- });
+ })) { return; }
cryptpadURL = cryptpadURL.replace(/(\/)+$/, '');
var url = cryptpadURL + '/integration/';
diff --git a/www/integration/main.js b/www/integration/main.js
index 9775809b4..ce7aceb1f 100644
--- a/www/integration/main.js
+++ b/www/integration/main.js
@@ -99,7 +99,7 @@ define([
isNew = true;
return Hash.createRandomHash('integration');
};
- var oldKey = data.sessionKey;
+ var oldKey = data.key;
if (!oldKey) { return void cb({ key: getHash() }); }
checkSession(oldKey, function (obj) {
@@ -112,33 +112,17 @@ define([
chan.on('START', function (data) {
console.warn('INNER START', data);
- nThen(function (w) {
- if (!isNew) { return; }
-
- // XXX initial content TBD
- var content = JSON.stringify({
- content: data.document,
- highlightMode: "gfm"
- }); // XXX only for code
-
- console.error('CRYPTPUT', data.key);
- Crypt.put(data.key, content, w(), {
- 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;
- });
+ 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,
+ initialState: isNew ? data.document : undefined
+ };
+ require(['/common/sframe-app-outer.js'], function () {
+ console.warn('SAO REQUIRED');
+ delete window.CP_integration_outer;
});
});