mirror of https://github.com/xwiki-labs/cryptpad
Merge branch 'staging' into 5.3-storage
This commit is contained in:
commit
6bb336034b
|
@ -52,6 +52,12 @@ body > .non-realtime:first-child + * {
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.cke_editable
|
||||
{
|
||||
font-size: 16px;
|
||||
|
|
|
@ -14,11 +14,6 @@ define([
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Msg.install_header = "CryptPad Install"; // XXX
|
||||
Msg.install_notes = "<ul class=\"cp-notes-list\"><li>Create your first admin account using this form.</li>" +
|
||||
"<li>Please note your password carefully. <span class=\"red\">If you lose it there is no way we can recover your data.</span></li></ul>"; // XXX
|
||||
*/
|
||||
Msg.install_token = "Install token";
|
||||
|
||||
document.title = Msg.install_header;
|
||||
|
|
|
@ -329,8 +329,6 @@ commands.ADD_INSTALL_TOKEN = function (Env, args) {
|
|||
|
||||
var token = args[0];
|
||||
|
||||
// XXX check length, etc. ?
|
||||
|
||||
Env.installToken = token;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -229,7 +229,7 @@ appIndexesToBuild.forEach(function (app) {
|
|||
|
||||
write(built, `./www/${app}/index.html`);
|
||||
|
||||
// XXX preloading version for inner.html
|
||||
// TODO preloading version for inner.html
|
||||
});
|
||||
|
||||
var instance;
|
||||
|
|
|
@ -22,7 +22,6 @@ nThen(function (w) {
|
|||
console.log('Existing token');
|
||||
token = Env.installToken;
|
||||
}
|
||||
// XXX IF ADMINS ABORT?
|
||||
}));
|
||||
}).nThen(function (w) {
|
||||
if (Env.installToken) { return; }
|
||||
|
|
|
@ -1397,8 +1397,8 @@ ICS ==> create a new event with the same UID and a RECURRENCE-ID field (with a v
|
|||
if (updatedOn) { delete APP.recurrenceRule._next; }
|
||||
APP.wasRecurrent = Boolean(APP.recurrenceRule);
|
||||
|
||||
// XXX TEST
|
||||
/*
|
||||
// Test data:
|
||||
APP.recurrenceRule = {
|
||||
freq: 'yearly',
|
||||
interval: 2,
|
||||
|
|
|
@ -146,6 +146,9 @@
|
|||
flex: 1;
|
||||
max-width: 100%;
|
||||
resize: none;
|
||||
.CodeMirror-sizer > div {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
#cp-app-code-preview {
|
||||
display: none !important;
|
||||
|
|
|
@ -332,6 +332,12 @@ define([
|
|||
: Messages.error;
|
||||
return void UI.warn(text);
|
||||
}
|
||||
sframeChan.query('Q_ACCEPT_OWNERSHIP', data, function (err, res) {
|
||||
if (err || (res && res.error)) {
|
||||
return void console.error(err || res.error);
|
||||
}
|
||||
UI.log(Messages.saved);
|
||||
});
|
||||
}));
|
||||
}
|
||||
}).nThen(function (waitFor) {
|
||||
|
@ -867,7 +873,7 @@ define([
|
|||
// In the properties, we should have the edit href if we know it.
|
||||
// We should know it because the pad is stored, but it's better to check...
|
||||
//if (!data.noEditPassword && !opts.noEditPassword && owned && data.href) {
|
||||
if (!data.noEditPassword && !opts.noEditPassword && owned && data.href && parsed.type !== "form") { // XXX password change in forms block responses (validation & decryption)
|
||||
if (!data.noEditPassword && !opts.noEditPassword && owned && data.href && parsed.type !== "form") { // TODO password change in forms block responses (validation & decryption)
|
||||
var isOO = parsed.type === 'sheet';
|
||||
var isFile = parsed.hashData.type === 'file';
|
||||
var isSharedFolder = parsed.type === 'drive';
|
||||
|
|
|
@ -2134,9 +2134,7 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
|
|||
var exportXLSXFile = function() {
|
||||
var text = getContent();
|
||||
var suggestion = Title.suggestTitle(Title.defaultTitle);
|
||||
var ext = ['.xlsx', '.ods', '.bin',
|
||||
//'.csv', // XXX 4.11.0
|
||||
'.pdf'];
|
||||
var ext = ['.xlsx', '.ods', '.bin', '.pdf'];
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
var warning = '';
|
||||
if (type==="presentation") {
|
||||
|
|
|
@ -1694,7 +1694,7 @@ define([
|
|||
var ed = Util.find(store, ['proxy', 'teams', teamId, 'keys', 'drive', 'edPublic']);
|
||||
var edPrivate = Util.find(store, ['proxy', 'teams', teamId, 'keys', 'drive', 'edPrivate']);
|
||||
if (allowed.indexOf(ed) === -1) { return false; }
|
||||
if (!edPrivate) { return false; } // XXX: Only editors can authenticate...
|
||||
if (!edPrivate) { return false; } // FIXME: Only editors can authenticate...
|
||||
// This team is allowed: use its rpc
|
||||
var t = teamModule.getTeam(teamId);
|
||||
_store = t;
|
||||
|
@ -1952,11 +1952,15 @@ define([
|
|||
// contactPadOwner is used to send "REQUEST_ACCESS" messages
|
||||
// and to notify form owners when sending a response
|
||||
Store.contactPadOwner = function (clientId, data, cb) {
|
||||
var owner = data.owner;
|
||||
var owners = data.owners;
|
||||
|
||||
// If send is true, send the request to the owner.
|
||||
if (owner) {
|
||||
if (data.send) {
|
||||
if (!Array.isArray(owners) || !owners.length) { return cb({state: false}); }
|
||||
|
||||
if (!data.send) { return void cb({state: true}); }
|
||||
|
||||
nThen(function (waitFor) {
|
||||
owners.forEach(function (owner) {
|
||||
var sendTo = function (query, msg, user, _cb) {
|
||||
if (store.mailbox && !data.anon) {
|
||||
return store.mailbox.sendTo(query, msg, user, _cb);
|
||||
|
@ -1969,14 +1973,11 @@ define([
|
|||
}, {
|
||||
channel: owner.notifications,
|
||||
curvePublic: owner.curvePublic
|
||||
}, function () {
|
||||
cb({state: true});
|
||||
});
|
||||
return;
|
||||
}
|
||||
return void cb({state: true});
|
||||
}
|
||||
cb({state: false});
|
||||
}, waitFor());
|
||||
});
|
||||
}).nThen(function () {
|
||||
cb({state: true});
|
||||
});
|
||||
};
|
||||
Store.givePadAccess = function (clientId, data, cb) {
|
||||
var edPublic = store.proxy.edPublic;
|
||||
|
|
|
@ -8,9 +8,10 @@ define([
|
|||
'/customize/messages.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
'chainpad-listmap',
|
||||
'/lib/datepicker/flatpickr.js',
|
||||
'/bower_components/chainpad-crypto/crypto.js',
|
||||
'/bower_components/chainpad/chainpad.dist.js',
|
||||
], function (Util, Hash, Constants, Realtime, Cache, Rec, Messages, nThen, Listmap, Crypto, ChainPad) {
|
||||
], function (Util, Hash, Constants, Realtime, Cache, Rec, Messages, nThen, Listmap, FP, Crypto, ChainPad) {
|
||||
var Calendar = {};
|
||||
|
||||
var getStore = function (ctx, id) {
|
||||
|
@ -131,9 +132,9 @@ define([
|
|||
var last = ctx.store.data.lastVisit;
|
||||
|
||||
if (ev.isAllDay) {
|
||||
if (ev.startDay) { ev.start = +new Date(ev.startDay); }
|
||||
if (ev.startDay) { ev.start = +FP.parseDate(ev.startDay); }
|
||||
if (ev.endDay) {
|
||||
var endDate = new Date(ev.endDay);
|
||||
var endDate = FP.parseDate(ev.endDay);
|
||||
endDate.setHours(23);
|
||||
endDate.setMinutes(59);
|
||||
endDate.setSeconds(59);
|
||||
|
@ -223,7 +224,7 @@ define([
|
|||
};
|
||||
var addReminders = function (ctx, id, ev) {
|
||||
var calendar = ctx.calendars[id];
|
||||
if (!ev) { return; } // XXX deleted event remote: delete reminders
|
||||
if (!ev) { return; }
|
||||
if (!calendar || !calendar.reminders) { return; }
|
||||
if (calendar.stores.length === 1 && calendar.stores[0] === 0) { return; }
|
||||
|
||||
|
@ -1063,7 +1064,6 @@ define([
|
|||
Calendar.init = function (cfg, waitFor, emit) {
|
||||
var calendar = {};
|
||||
var store = cfg.store;
|
||||
//if (!store.loggedIn || !store.proxy.edPublic) { return; } // XXX logged in only? we should al least allow read-only for URL calendars
|
||||
var ctx = {
|
||||
loggedIn: store.loggedIn && store.proxy.edPublic,
|
||||
store: store,
|
||||
|
|
|
@ -470,7 +470,6 @@ var factory = function (Util, Hash, CPNetflux, Sortify, nThen, Crypto, Feedback)
|
|||
delete clone.previewChannel;
|
||||
members[curve] = clone;
|
||||
|
||||
// XXX
|
||||
var remaining = members[author].remaining || 1;
|
||||
if (remaining === -1) { return true; } // Infinite uses, keep the link
|
||||
if (remaining > 1) { // Remove 1 use
|
||||
|
|
|
@ -856,7 +856,7 @@ define([
|
|||
}
|
||||
}
|
||||
if (!Hash.isValidChannel(el.channel)) {
|
||||
// XXX delete channel? replace with parsed.channel?
|
||||
// FIXME delete channel? replace with parsed.channel?
|
||||
console.error('Remove invalid channel', el.channel, el);
|
||||
// toClean.push(id);
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ define([
|
|||
var obj = Util.clone(proxy.metadata || {});
|
||||
|
||||
for (var k in Env.user.proxy[UserObject.SHARED_FOLDERS][id] || {}) {
|
||||
if (typeof(Env.user.proxy[UserObject.SHARED_FOLDERS][id][k]) === "undefined") { // XXX "deleted folder" for restricted shared folders when viewer in a team
|
||||
if (typeof(Env.user.proxy[UserObject.SHARED_FOLDERS][id][k]) === "undefined") { // TODO "deleted folder" for restricted shared folders when viewer in a team
|
||||
continue;
|
||||
}
|
||||
var data = Util.clone(Env.user.proxy[UserObject.SHARED_FOLDERS][id][k]);
|
||||
|
|
|
@ -140,10 +140,15 @@ define([
|
|||
return text.trim();
|
||||
};
|
||||
|
||||
var isMobile = /Android|iPhone/i.test(navigator.userAgent);
|
||||
|
||||
module.mkIndentSettings = function (editor, metadataMgr) {
|
||||
var setIndentation = function (units, useTabs, fontSize, spellcheck, brackets) {
|
||||
if (typeof(units) !== 'number') { return; }
|
||||
var doc = editor.getDoc();
|
||||
if (isMobile && fontSize < 16) {
|
||||
fontSize = 16;
|
||||
}
|
||||
editor.setOption('indentUnit', units);
|
||||
editor.setOption('tabSize', units);
|
||||
editor.setOption('indentWithTabs', useTabs);
|
||||
|
|
|
@ -943,6 +943,50 @@ define([
|
|||
}, href);
|
||||
});
|
||||
|
||||
sframeChan.on('Q_ACCEPT_OWNERSHIP', function (data, cb) {
|
||||
var parsed = Utils.Hash.parsePadUrl(data.href);
|
||||
if (parsed.type === 'drive') {
|
||||
// Shared folder
|
||||
var secret = Utils.Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||
Cryptpad.addSharedFolder(null, secret, cb);
|
||||
} else {
|
||||
var _data = {
|
||||
password: data.password,
|
||||
href: data.href,
|
||||
channel: data.channel,
|
||||
title: data.title,
|
||||
owners: data.metadata ? data.metadata.owners : data.owners,
|
||||
expire: data.metadata ? data.metadata.expire : data.expire,
|
||||
forceSave: true
|
||||
};
|
||||
Cryptpad.setPadTitle(_data, function (err) {
|
||||
cb({error: err});
|
||||
});
|
||||
}
|
||||
|
||||
// Also add your mailbox to the metadata object
|
||||
var padParsed = Utils.Hash.parsePadUrl(data.href);
|
||||
var padSecret = Utils.Hash.getSecrets(padParsed.type, padParsed.hash, data.password);
|
||||
var padCrypto = Utils.Crypto.createEncryptor(padSecret.keys);
|
||||
try {
|
||||
var value = {};
|
||||
value[edPublic] = padCrypto.encrypt(JSON.stringify({
|
||||
notifications: notifications,
|
||||
curvePublic: curvePublic
|
||||
}));
|
||||
var msg = {
|
||||
channel: data.channel,
|
||||
command: 'ADD_MAILBOX',
|
||||
value: value
|
||||
};
|
||||
Cryptpad.setPadMetadata(msg, function (res) {
|
||||
if (res.error) { console.error(res.error); }
|
||||
});
|
||||
} catch (err) {
|
||||
return void console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
// Add or remove our mailbox from the list if we're an owner
|
||||
sframeChan.on('Q_UPDATE_MAILBOX', function (data, cb) {
|
||||
var metadata = data.metadata;
|
||||
|
@ -1024,7 +1068,7 @@ define([
|
|||
}
|
||||
var send = data.send;
|
||||
var metadata = data.metadata;
|
||||
var owner, owners;
|
||||
var owners = [];
|
||||
var _secret = secret;
|
||||
if (metadata && metadata.roHref) {
|
||||
var _parsed = Utils.Hash.parsePadUrl(metadata.roHref);
|
||||
|
@ -1037,24 +1081,24 @@ define([
|
|||
nThen(function (waitFor) {
|
||||
// Try to get the owner's mailbox from the pad metadata first.
|
||||
var todo = function (obj) {
|
||||
owners = obj.owners;
|
||||
|
||||
var mailbox;
|
||||
// Get the first available mailbox (the field can be an string or an object)
|
||||
// TODO maybe we should send the request to all the owners?
|
||||
if (typeof (obj.mailbox) === "string") {
|
||||
mailbox = obj.mailbox;
|
||||
} else if (obj.mailbox && obj.owners && obj.owners.length) {
|
||||
mailbox = obj.mailbox[obj.owners[0]];
|
||||
}
|
||||
if (mailbox) {
|
||||
var decrypt = function (mailbox) {
|
||||
try {
|
||||
var dataStr = crypto.decrypt(mailbox, true, true);
|
||||
var data = JSON.parse(dataStr);
|
||||
if (!data.notifications || !data.curvePublic) { return; }
|
||||
owner = data;
|
||||
return data;
|
||||
} catch (e) { console.error(e); }
|
||||
};
|
||||
if (typeof (obj.mailbox) === "string") {
|
||||
owners = [decrypt(obj.mailbox)];
|
||||
return;
|
||||
}
|
||||
if (!obj.mailbox || !obj.owners || !obj.owners.length) { return; }
|
||||
owners = obj.owners.map(function (edPublic) {
|
||||
var mailbox = obj.mailbox[edPublic];
|
||||
if (typeof(mailbox) !== "string") { return; }
|
||||
return decrypt(mailbox);
|
||||
}).filter(Boolean);
|
||||
};
|
||||
|
||||
// If we already have metadata, use it, otherwise, try to get it
|
||||
|
@ -1069,7 +1113,7 @@ define([
|
|||
}));
|
||||
}).nThen(function () {
|
||||
// If we are just checking (send === false) and there is a mailbox field, cb state true
|
||||
if (!send) { return void cb({state: Boolean(owner)}); }
|
||||
if (!send) { return void cb({state: Boolean(owners.length)}); }
|
||||
|
||||
Cryptpad.padRpc.contactOwner({
|
||||
send: send,
|
||||
|
@ -1077,7 +1121,6 @@ define([
|
|||
query: data.query,
|
||||
msgData: data.msgData,
|
||||
channel: _secret.channel,
|
||||
owner: owner,
|
||||
owners: owners
|
||||
}, cb);
|
||||
});
|
||||
|
@ -1238,50 +1281,6 @@ define([
|
|||
});
|
||||
});
|
||||
|
||||
sframeChan.on('Q_ACCEPT_OWNERSHIP', function (data, cb) {
|
||||
var parsed = Utils.Hash.parsePadUrl(data.href);
|
||||
if (parsed.type === 'drive') {
|
||||
// Shared folder
|
||||
var secret = Utils.Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||
Cryptpad.addSharedFolder(null, secret, cb);
|
||||
} else {
|
||||
var _data = {
|
||||
password: data.password,
|
||||
href: data.href,
|
||||
channel: data.channel,
|
||||
title: data.title,
|
||||
owners: data.metadata.owners,
|
||||
expire: data.metadata.expire,
|
||||
forceSave: true
|
||||
};
|
||||
Cryptpad.setPadTitle(_data, function (err) {
|
||||
cb({error: err});
|
||||
});
|
||||
}
|
||||
|
||||
// Also add your mailbox to the metadata object
|
||||
var padParsed = Utils.Hash.parsePadUrl(data.href);
|
||||
var padSecret = Utils.Hash.getSecrets(padParsed.type, padParsed.hash, data.password);
|
||||
var padCrypto = Utils.Crypto.createEncryptor(padSecret.keys);
|
||||
try {
|
||||
var value = {};
|
||||
value[edPublic] = padCrypto.encrypt(JSON.stringify({
|
||||
notifications: notifications,
|
||||
curvePublic: curvePublic
|
||||
}));
|
||||
var msg = {
|
||||
channel: data.channel,
|
||||
command: 'ADD_MAILBOX',
|
||||
value: value
|
||||
};
|
||||
Cryptpad.setPadMetadata(msg, function (res) {
|
||||
if (res.error) { console.error(res.error); }
|
||||
});
|
||||
} catch (err) {
|
||||
return void console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
sframeChan.on('Q_IMPORT_MEDIATAG', function (obj, cb) {
|
||||
var key = obj.key;
|
||||
var channel = obj.channel;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
define([], function () {
|
||||
if (window.__CRYPTPAD_TEST_OBJ_) { return window.__CRYPTPAD_TEST_OBJ_; }
|
||||
/*
|
||||
// XXX localhost secureiframe fix
|
||||
var out = function () {};
|
||||
out.options = {};
|
||||
out.testing = false;
|
||||
|
|
|
@ -294,6 +294,7 @@ define([
|
|||
|
||||
Messages.convertPage = "Convert"; // XXX 4.11.0
|
||||
Messages.convert_hint = "Pick the file you want to convert. The list of output format will be visible afterwards."; // XXX 4.11.0
|
||||
Messages.convert_unsupported = "UNSUPPORTED FILE TYPE :("; // XXX
|
||||
|
||||
var createToolbar = function () {
|
||||
var displayed = ['useradmin', 'newpad', 'limit', 'pageTitle', 'notifications'];
|
||||
|
@ -328,7 +329,6 @@ define([
|
|||
type: 'file'
|
||||
});
|
||||
APP.$rightside.append([hint, picker]);
|
||||
Messages.convert_unsupported = "UNSUPPORTED FILE TYPE :("; // XXX
|
||||
|
||||
$(picker).on('change', function () {
|
||||
APP.$rightside.find('button, div.notice').remove();
|
||||
|
|
|
@ -4005,7 +4005,7 @@ define([
|
|||
$container.empty().append(_content);
|
||||
|
||||
|
||||
// XXX Delete key form_updateMsg
|
||||
// XXX Delete translation key form_updateMsg
|
||||
if (editable) {
|
||||
var responseMsg = h('div.cp-form-response-msg-container');
|
||||
var $responseMsg = $(responseMsg).appendTo($container);
|
||||
|
|
|
@ -314,7 +314,7 @@ define([
|
|||
if (obj && obj.error) { err = obj.error; return; }
|
||||
var messages = obj.messages;
|
||||
if (!messages.length) {
|
||||
// XXX TODO delete from drive.forms
|
||||
// TODO delete from drive.forms?
|
||||
return;
|
||||
}
|
||||
if (obj.lastKnownHash !== answer.hash) { return; }
|
||||
|
|
|
@ -79,7 +79,7 @@ define([
|
|||
Env.metadataMgr.updateMetadata(md);
|
||||
};
|
||||
|
||||
var sendReplyNotification = function(Env, uid) {
|
||||
var sendReplyNotification = function(Env, uid, mentionedCurve) {
|
||||
if (!Env.comments || !Env.comments.data || !Env.comments.authors) { return; }
|
||||
if (!Env.common.isLoggedIn()) { return; }
|
||||
var thread = Env.comments.data[uid];
|
||||
|
@ -88,8 +88,6 @@ define([
|
|||
var privateData = Env.metadataMgr.getPrivateData();
|
||||
var others = {};
|
||||
|
||||
|
||||
// XXX mentioned users should be excluded from the list of notified recipients to avoid notifying them twice
|
||||
// Get all the other registered users with a mailbox
|
||||
thread.m.forEach(function(obj) {
|
||||
var u = obj.u;
|
||||
|
@ -97,6 +95,9 @@ define([
|
|||
var author = Env.comments.authors[u];
|
||||
if (!author || others[u] || !author.notifications || !author.curvePublic) { return; }
|
||||
if (author.curvePublic === userData.curvePublic) { return; } // don't send to yourself
|
||||
if (Object.keys(mentionedCurve || {}).includes(author.curvePublic)) {
|
||||
return; // Don't send to mentioned users
|
||||
}
|
||||
others[u] = {
|
||||
curvePublic: author.curvePublic,
|
||||
comment: obj.m,
|
||||
|
@ -203,7 +204,7 @@ define([
|
|||
});
|
||||
|
||||
// Push the content
|
||||
cb(content);
|
||||
cb(content, notify);
|
||||
});
|
||||
$(cancel).click(function(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -525,7 +526,7 @@ define([
|
|||
$(reply).click(function(e) {
|
||||
e.stopPropagation();
|
||||
$actions.hide();
|
||||
var form = getCommentForm(Env, key, function(val) {
|
||||
var form = getCommentForm(Env, key, function(val, mentioned) {
|
||||
// Show the "reply" and "resolve" buttons again
|
||||
$(form).closest('.cp-comment-container')
|
||||
.find('.cp-comment-actions').css('display', '');
|
||||
|
@ -551,7 +552,7 @@ define([
|
|||
});
|
||||
|
||||
// Notify other users
|
||||
sendReplyNotification(Env, key);
|
||||
sendReplyNotification(Env, key, mentioned);
|
||||
|
||||
// Send to chainpad
|
||||
updateMetadata(Env);
|
||||
|
|
|
@ -903,6 +903,10 @@ define([
|
|||
$toc.addClass('hidden');
|
||||
localHide = true;
|
||||
if (store) { store.put(key, '1'); }
|
||||
|
||||
if (APP.tocScroll) {
|
||||
APP.tocScroll();
|
||||
}
|
||||
});
|
||||
$(showBtn).click(function () {
|
||||
$toc.removeClass('hidden');
|
||||
|
@ -922,6 +926,23 @@ define([
|
|||
e.stopPropagation();
|
||||
if (!obj.el || UIElements.isVisible(obj.el, $contentContainer)) { return; }
|
||||
obj.el.scrollIntoView();
|
||||
var $iframe = $('iframe').contents();
|
||||
var onScroll = function () {
|
||||
APP.tocScrollOff();
|
||||
};
|
||||
APP.tocScrollOff = function () {
|
||||
delete APP.tocScroll;
|
||||
delete APP.tocScrollOff;
|
||||
$iframe.off('scroll', onScroll);
|
||||
};
|
||||
APP.tocScroll = function () {
|
||||
obj.el.scrollIntoView();
|
||||
APP.tocScrollOff();
|
||||
};
|
||||
//$(window).on('scroll', onScroll);
|
||||
setTimeout(function () {
|
||||
$iframe.on('scroll', onScroll);
|
||||
});
|
||||
});
|
||||
a.innerHTML = title;
|
||||
content.push(h('p.cp-pad-toc-'+level, a));
|
||||
|
@ -1003,6 +1024,8 @@ define([
|
|||
if (scrollMax) {
|
||||
$iframe.scrollTop($iframe.innerHeight());
|
||||
}
|
||||
|
||||
if (APP.tocScrollOff) { APP.tocScrollOff(); }
|
||||
});
|
||||
|
||||
framework.setTextContentGetter(function() {
|
||||
|
@ -1017,6 +1040,8 @@ define([
|
|||
return str;
|
||||
});
|
||||
framework.setContentGetter(function() {
|
||||
if (APP.tocScrollOff) { APP.tocScrollOff(); }
|
||||
|
||||
$inner.find('span[data-cke-display-name="media-tag"]:empty').each(function(i, el) {
|
||||
$(el).remove();
|
||||
});
|
||||
|
|
|
@ -28,7 +28,7 @@ define([
|
|||
};
|
||||
window.rc = requireConfig;
|
||||
window.apiconf = ApiConfig;
|
||||
// XXX extra sandboxing features are temporarily disabled as I suspect this is the cause of a regression in Safari
|
||||
// FIXME extra sandboxing features are temporarily disabled as I suspect this is the cause of a regression in Safari
|
||||
$('#sbox-secure-iframe')/*.attr('sandbox', 'allow-scripts allow-popups allow-modals')*/.attr('src',
|
||||
ApiConfig.httpSafeOrigin + '/secureiframe/inner.html?' + requireConfig.urlArgs +
|
||||
'#' + encodeURIComponent(JSON.stringify(req)));
|
||||
|
|
|
@ -147,6 +147,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
@media (max-width: @browser_media-medium-screen) {
|
||||
#cp-app-slide-editor {
|
||||
#cp-app-slide-editor-container {
|
||||
.CodeMirror-sizer > div {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Slide position (print mode) */
|
||||
@ratio:0.9;
|
||||
@media print {
|
||||
|
|
Loading…
Reference in New Issue