Open static spreadsheets (xlsx, ods) in the sheet app

pull/1/head
yflory 3 years ago
parent 51ba5d22da
commit 2e1deeb8ed

@ -573,6 +573,26 @@
return false;
};
// Tell if a file is spreadsheet from its metadata={title, fileType}
Util.isSpreadsheet = function (type, name) {
return (type &&
(type === 'application/vnd.oasis.opendocument.spreadsheet' ||
type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
|| (name && (name.endsWith('.xlsx') || name.endsWith('.ods')));
};
Util.isOfficeDoc = function (type, name) {
return (type &&
(type === 'application/vnd.oasis.opendocument.text' ||
type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'))
|| (name && (name.endsWith('.docx') || name.endsWith('.odt')));
};
Util.isPresentation = function (type, name) {
return (type &&
(type === 'application/vnd.oasis.opendocument.presentation' ||
type === 'application/vnd.openxmlformats-officedocument.presentationml.presentation'))
|| (name && (name.endsWith('.pptx') || name.endsWith('.odp')));
};
Util.isValidURL = function (str) {
var pattern = new RegExp('^(https?:\\/\\/)'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name

@ -89,7 +89,10 @@ define([
var faShared = 'fa-shhare-alt';
var faReadOnly = 'fa-eye';
var faPreview = 'fa-eye';
var faOpenInCode = 'cptools-code';
var faOpenInCode = AppConfig.applicationsIcon.code;
var faOpenInSheet = AppConfig.applicationsIcon.sheet;
var faOpenInDoc = AppConfig.applicationsIcon.doc;
var faOpenInPresentation = AppConfig.applicationsIcon.presentation;
var faRename = 'fa-pencil';
var faColor = 'cptools-palette';
var faTrash = 'fa-trash';
@ -332,6 +335,9 @@ define([
};
Messages.fc_openInSheet = "Edit in Sheet"; // XXX
Messages.fc_openInDoc = "Edit in Document"; // XXX
Messages.fc_openInPresentation = "Edit in Presentation"; // XXX
var createContextMenu = function () {
var menu = h('div.cp-contextmenu.dropdown.cp-unselectable', [
h('ul.dropdown-menu', {
@ -356,6 +362,18 @@ define([
'tabindex': '-1',
'data-icon': faOpenInCode,
}, Messages.fc_openInCode)),
h('li', h('a.cp-app-drive-context-openinsheet.dropdown-item', {
'tabindex': '-1',
'data-icon': faOpenInSheet,
}, Messages.fc_openInSheet)),
h('li', h('a.cp-app-drive-context-openindoc.dropdown-item', {
'tabindex': '-1',
'data-icon': faOpenInDoc,
}, Messages.fc_openInDoc)),
h('li', h('a.cp-app-drive-context-openinpresentation.dropdown-item', {
'tabindex': '-1',
'data-icon': faOpenInPresentation,
}, Messages.fc_openInPresentation)),
h('li', h('a.cp-app-drive-context-savelocal.dropdown-item', {
'tabindex': '-1',
'data-icon': 'fa-cloud-upload',
@ -1293,6 +1311,18 @@ define([
if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) {
hide.push('openincode');
}
if (!metadata || !Util.isSpreadsheet(metadata.fileType, metadata.title)
|| !priv.supportsWasm) {
hide.push('openinsheet');
}
if (!metadata || !Util.isOfficeDoc(metadata.fileType, metadata.title)
|| !priv.supportsWasm) {
hide.push('openindoc');
}
if (!metadata || !Util.isPresentation(metadata.fileType, metadata.title)
|| !priv.supportsWasm) {
hide.push('openinpresentation');
}
if (metadata.channel && metadata.channel.length < 48) {
hide.push('preview');
}
@ -1309,6 +1339,9 @@ define([
containsFolder = true;
hide.push('openro');
hide.push('openincode');
hide.push('openinsheet');
hide.push('openindoc');
hide.push('openinpresentation');
hide.push('hashtag');
//hide.push('delete');
hide.push('makeacopy');
@ -1324,6 +1357,9 @@ define([
hide.push('savelocal');
hide.push('openro');
hide.push('openincode');
hide.push('openinsheet');
hide.push('openindoc');
hide.push('openinpresentation');
hide.push('properties', 'access');
hide.push('hashtag');
hide.push('makeacopy');
@ -1355,7 +1391,8 @@ define([
hide.push('download');
hide.push('share');
hide.push('savelocal');
hide.push('openincode'); // can't because of race condition
//hide.push('openincode'); // can't because of race condition
//hide.push('openinsheet'); // can't because of race condition
hide.push('makeacopy');
hide.push('preview');
}
@ -1380,11 +1417,12 @@ define([
break;
case 'tree':
show = ['open', 'openro', 'preview', 'openincode', 'expandall', 'collapseall',
'color', 'download', 'share', 'savelocal', 'rename', 'delete', 'makeacopy',
'color', 'download', 'share', 'savelocal', 'rename', 'delete',
'makeacopy', 'openinsheet', 'openindoc', 'openinpresentation',
'deleteowned', 'removesf', 'access', 'properties', 'hashtag'];
break;
case 'default':
show = ['open', 'openro', 'preview', 'openincode', 'share', 'download', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy', 'savelocal', 'rename'];
show = ['open', 'openro', 'preview', 'openincode', 'openinsheet', 'openindoc', 'openinpresentation', 'share', 'download', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy', 'savelocal', 'rename'];
break;
case 'trashtree': {
show = ['empty'];
@ -4349,6 +4387,21 @@ define([
});
};
var openInApp = function (paths, app) {
var p = paths[0];
var el = manager.find(p.path);
var path = currentPath;
if (path[0] !== ROOT) { path = [ROOT]; }
var _metadata = manager.getFileData(el);
var _simpleData = {
title: _metadata.filename || _metadata.title,
href: _metadata.href || _metadata.roHref,
fileType: _metadata.fileType,
password: _metadata.password,
channel: _metadata.channel,
};
openIn(app, path, APP.team, _simpleData);
};
$contextMenu.on("click", "a", function(e) {
e.stopPropagation();
@ -4436,20 +4489,19 @@ define([
}
else if ($this.hasClass('cp-app-drive-context-openincode')) {
if (paths.length !== 1) { return; }
var p = paths[0];
el = manager.find(p.path);
(function () {
var path = currentPath;
if (path[0] !== ROOT) { path = [ROOT]; }
var _metadata = manager.getFileData(el);
var _simpleData = {
title: _metadata.filename || _metadata.title,
href: _metadata.href || _metadata.roHref,
password: _metadata.password,
channel: _metadata.channel,
};
openIn('code', path, APP.team, _simpleData);
})();
openInApp(paths, 'code');
}
else if ($this.hasClass('cp-app-drive-context-openinsheet')) {
if (paths.length !== 1) { return; }
openInApp(paths, 'sheet');
}
else if ($this.hasClass('cp-app-drive-context-openindoc')) {
if (paths.length !== 1) { return; }
openInApp(paths, 'doc');
}
else if ($this.hasClass('cp-app-drive-context-openinpresentation')) {
if (paths.length !== 1) { return; }
openInApp(paths, 'presentation');
}
else if ($this.hasClass('cp-app-drive-context-expandall') ||
$this.hasClass('cp-app-drive-context-collapseall')) {

@ -1331,8 +1331,8 @@ define([
var x2tConvertData = function (data, fileName, format, cb) {
var sframeChan = common.getSframeChannel();
var e = getEditor();
var fonts = e.FontLoader.fontInfos;
var files = e.FontLoader.fontFiles.map(function (f) {
var fonts = e && e.FontLoader.fontInfos;
var files = e && e.FontLoader.fontFiles.map(function (f) {
return { 'Id': f.Id, };
});
var type = common.getMetadataMgr().getPrivateData().ooType;
@ -1341,7 +1341,7 @@ define([
type: type,
fileName: fileName,
outputFormat: format,
images: window.frames[0].AscCommon.g_oDocumentUrls.urls || {},
images: (e && window.frames[0].AscCommon.g_oDocumentUrls.urls) || {},
fonts: fonts,
fonts_files: files,
mediasSources: getMediasSources(),
@ -2643,9 +2643,99 @@ define([
return;
}
var next = function () {
loadDocument(newDoc, useNewDefault);
setEditable(!readOnly);
UI.removeLoadingScreen();
};
if (privateData.isNewFile && privateData.fromFileData) {
try {
(function () {
var data = privateData.fromFileData;
var type = data.fileType;
var title = data.title;
// Fix extension if the file was renamed
if (Util.isSpreadsheet(type) && !Util.isSpreadsheet(data.title)) {
if (type === 'application/vnd.oasis.opendocument.spreadsheet') {
data.title += '.ods';
}
if (type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
data.title += '.xlsx';
}
}
if (Util.isOfficeDoc(type) && !Util.isOfficeDoc(data.title)) {
if (type === 'application/vnd.oasis.opendocument.text') {
data.title += '.odt';
}
if (type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
data.title += '.docx';
}
}
if (Util.isPresentation(type) && !Util.isPresentation(data.title)) {
if (type === 'application/vnd.oasis.opendocument.presentation') {
data.title += '.odp';
}
if (type === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
data.title += '.pptx';
}
}
var href = data.href;
var password = data.password;
var parsed = Hash.parsePadUrl(href);
var secret = Hash.getSecrets('file', parsed.hash, password);
var hexFileName = secret.channel;
var fileHost = privateData.fileHost || privateData.origin;
var src = fileHost + Hash.getBlobPathFromHex(hexFileName);
var key = secret.keys && secret.keys.cryptKey;
var xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (/^4/.test('' + this.status)) {
// fallback to empty sheet
console.error(this.status);
return void next();
}
var arrayBuffer = xhr.response;
if (arrayBuffer) {
var u8 = new Uint8Array(arrayBuffer);
FileCrypto.decrypt(u8, key, function (err, decrypted) {
if (err) {
// fallback to empty sheet
console.error(err);
return void next();
}
var blobXlsx = decrypted.content;
new Response(blobXlsx).arrayBuffer().then(function (buffer) {
var u8Xlsx = new Uint8Array(buffer);
x2tImportData(u8Xlsx, data.title, 'bin', function (bin) {
var blob = new Blob([bin], {type: 'text/plain'});
startOO(blob, getFileType());
Title.updateTitle(title);
UI.removeLoadingScreen();
});
});
});
}
};
xhr.onerror = function (err) {
// fallback to empty sheet
console.error(err);
next();
};
xhr.send(null);
})();
} catch (e) {
console.error(e);
next();
}
return;
}
next();
});
};

@ -574,6 +574,7 @@ define([
var edPublic, curvePublic, notifications, isTemplate;
var settings = {};
var isSafe = ['debug', 'profile', 'drive', 'teams', 'calendar', 'file'].indexOf(currentPad.app) !== -1;
var isOO = ['sheet', 'doc', 'presentation'].indexOf(parsed.type) !== -1;
var ooDownloadData = {};
var isDeleted = isNewFile && currentPad.hash.length > 0;
@ -634,9 +635,9 @@ define([
channel: secret.channel,
enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default
devMode: localStorage.CryptPad_dev === "1",
fromFileData: Cryptpad.fromFileData ? {
fromFileData: Cryptpad.fromFileData ? (isOO ? Cryptpad.fromFileData : {
title: Cryptpad.fromFileData.title
} : undefined,
}) : undefined,
burnAfterReading: burnAfterReading,
storeInTeam: Cryptpad.initialTeam || (Cryptpad.initialPath ? -1 : undefined),
supportsWasm: Utils.Util.supportsWasm()
@ -2016,7 +2017,7 @@ define([
return;
}
// if we open a new code from a file
if (Cryptpad.fromFileData) {
if (Cryptpad.fromFileData && !isOO) {
Cryptpad.useFile(Cryptget, function (err) {
if (err) {
// TODO: better messages in case of expired, deleted, etc.?

Loading…
Cancel
Save